Merge pull request #12036 from CodaFi/rank-existentialist-nonsense
[NFC] Remove Existential Ranking Hack
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ec89e5f..a45727a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,8 @@
Swift 4.0
---------
+### 2017-09-19 (Xcode 9.0)
+
* [SE-0165][] and [SE-0154][]
The standard library's `Dictionary` and `Set` types have some new features. You can now create a new dictionary from a sequence of keys and values, and merge keys and values into an existing dictionary.
@@ -6710,3 +6712,9 @@
[SE-0177]: <https://github.com/apple/swift-evolution/blob/master/proposals/0177-add-clamped-to-method.md>
[SE-0178]: <https://github.com/apple/swift-evolution/blob/master/proposals/0178-character-unicode-view.md>
[SE-0179]: <https://github.com/apple/swift-evolution/blob/master/proposals/0179-swift-run-command.md>
+[SE-0180]: <https://github.com/apple/swift-evolution/blob/master/proposals/0180-string-index-overhaul.md>
+[SE-0181]: <https://github.com/apple/swift-evolution/blob/master/proposals/0181-package-manager-cpp-language-version.md>
+[SE-0182]: <https://github.com/apple/swift-evolution/blob/master/proposals/0182-newline-escape-in-strings.md>
+[SE-0183]: <https://github.com/apple/swift-evolution/blob/master/proposals/0183-substring-affordances.md>
+[SE-0184]: <https://github.com/apple/swift-evolution/blob/master/proposals/0184-unsafe-pointers-add-missing.md>
+[SE-0185]: <https://github.com/apple/swift-evolution/blob/master/proposals/0185-synthesize-equatable-hashable.md>
diff --git a/README.md b/README.md
index f773f21..dbbfe3b 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@
#### macOS
-To build for macOS, you need [Xcode 9.0 beta 6](https://developer.apple.com/xcode/downloads/).
+To build for macOS, you need [Xcode 9.0](https://developer.apple.com/xcode/downloads/).
The required version of Xcode changes frequently, and is often a beta release.
Check this document or the host information on <https://ci.swift.org> for the
current required version.
diff --git a/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake b/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
index 969994d..bf7f6bc 100644
--- a/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
+++ b/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
@@ -1,7 +1,6 @@
include(CMakeParseArguments)
-
# Run a shell command and assign output to a variable or fail with an error.
# Example usage:
# runcmd(COMMAND "xcode-select" "-p"
@@ -20,6 +19,57 @@
set(${RUNCMD_VARIABLE} ${${RUNCMD_VARIABLE}} PARENT_SCOPE)
endfunction(runcmd)
+function (add_swift_benchmark_library objfile_out sibfile_out)
+ cmake_parse_arguments(BENCHLIB "" "MODULE_PATH;SOURCE_DIR;OBJECT_DIR" "SOURCES;LIBRARY_FLAGS" ${ARGN})
+
+ precondition(BENCHLIB_MODULE_PATH)
+ precondition(BENCHLIB_SOURCE_DIR)
+ precondition(BENCHLIB_OBJECT_DIR)
+ precondition(BENCHLIB_SOURCES)
+
+ set(module_name_path "${BENCHLIB_MODULE_PATH}")
+ get_filename_component(module_name "${module_name_path}" NAME)
+ set(srcdir "${BENCHLIB_SOURCE_DIR}")
+ set(objdir "${BENCHLIB_OBJECT_DIR}")
+ set(sources "${BENCHLIB_SOURCES}")
+
+ set(objfile "${objdir}/${module_name}.o")
+ set(swiftmodule "${objdir}/${module_name}.swiftmodule")
+
+ precondition(objfile_out)
+ add_custom_command(
+ OUTPUT "${objfile}"
+ DEPENDS ${stdlib_dependencies} ${sources}
+ COMMAND "${SWIFT_EXEC}"
+ ${BENCHLIB_LIBRARY_FLAGS}
+ "-force-single-frontend-invocation"
+ "-parse-as-library"
+ "-module-name" "${module_name}"
+ "-emit-module" "-emit-module-path" "${swiftmodule}"
+ "-o" "${objfile}"
+ ${sources})
+ set(${objfile_out} "${objfile}" PARENT_SCOPE)
+
+ if(SWIFT_BENCHMARK_EMIT_SIB)
+ precondition(sibfile_out)
+ set(sibfile "${objdir}/${module_name}.sib")
+
+ add_custom_command(
+ OUTPUT "${sibfile}"
+ DEPENDS
+ ${stdlib_dependencies} ${sources}
+ COMMAND "${SWIFT_EXEC}"
+ ${BENCHLIB_LIBRARY_FLAGS}
+ "-force-single-frontend-invocation"
+ "-parse-as-library"
+ "-module-name" "${module_name}"
+ "-emit-sib"
+ "-o" "${sibfile}"
+ ${sources})
+ set(sibfile_out "${sibfile}" PARENT_SCOPE)
+ endif()
+endfunction()
+
function (swift_benchmark_compile_archopts)
cmake_parse_arguments(BENCH_COMPILE_ARCHOPTS "" "PLATFORM;ARCH;OPT" "" ${ARGN})
set(sdk ${${BENCH_COMPILE_ARCHOPTS_PLATFORM}_sdk})
@@ -67,84 +117,43 @@
set(bench_library_objects)
set(bench_library_sibfiles)
foreach(module_name_path ${BENCH_DRIVER_LIBRARY_MODULES})
- get_filename_component(module_name "${module_name_path}" NAME)
+ set(sources "${srcdir}/${module_name_path}.swift")
+ get_filename_component(module_name "${module_name_path}" NAME)
if("${module_name}" STREQUAL "DriverUtils")
- set(extra_sources "${srcdir}/utils/ArgParse.swift")
+ list(APPEND sources "${srcdir}/utils/ArgParse.swift")
endif()
- set(objfile "${objdir}/${module_name}.o")
- set(swiftmodule "${objdir}/${module_name}.swiftmodule")
- list(APPEND bench_library_objects "${objfile}")
- set(source "${srcdir}/${module_name_path}.swift")
- add_custom_command(
- OUTPUT "${objfile}"
- DEPENDS ${stdlib_dependencies} "${source}" ${extra_sources}
- COMMAND "${SWIFT_EXEC}"
- ${common_options_driver}
- ${BENCH_DRIVER_LIBRARY_FLAGS}
- "-force-single-frontend-invocation"
- "-parse-as-library"
- "-module-name" "${module_name}"
- "-emit-module" "-emit-module-path" "${swiftmodule}"
- "-o" "${objfile}"
- "${source}" ${extra_sources})
- if(SWIFT_BENCHMARK_EMIT_SIB)
- set(sibfile "${objdir}/${module_name}.sib")
- list(APPEND bench_library_sibfiles "${sibfile}")
- add_custom_command(
- OUTPUT "${sibfile}"
- DEPENDS
- ${stdlib_dependencies} "${srcdir}/${module_name_path}.swift"
- ${extra_sources}
- COMMAND "${SWIFT_EXEC}"
- ${common_options_driver}
- ${BENCH_DRIVER_LIBRARY_FLAGS}
- "-force-single-frontend-invocation"
- "-parse-as-library"
- "-module-name" "${module_name}"
- "-emit-sib"
- "-o" "${sibfile}"
- "${source}" ${extra_sources})
+ set(objfile_out)
+ set(sibfile_out)
+ add_swift_benchmark_library(objfile_out sibfile_out
+ MODULE_PATH "${module_name_path}"
+ SOURCE_DIR "${srcdir}"
+ OBJECT_DIR "${objdir}"
+ SOURCES ${sources}
+ LIBRARY_FLAGS ${common_options_driver} ${BENCH_DRIVER_LIBRARY_FLAGS})
+ precondition(objfile_out)
+ list(APPEND bench_library_objects "${objfile_out}")
+ if (SWIFT_BENCHMARK_EMIT_SIB)
+ precondition(sibfile_out)
+ list(APPEND bench_library_sibfiles "${sibfile_out}")
endif()
endforeach()
foreach(module_name_path ${BENCH_LIBRARY_MODULES})
- get_filename_component(module_name "${module_name_path}" NAME)
+ set(sources "${srcdir}/${module_name_path}.swift")
- set(objfile "${objdir}/${module_name}.o")
- set(swiftmodule "${objdir}/${module_name}.swiftmodule")
- set(source "${srcdir}/${module_name_path}.swift")
- list(APPEND bench_library_objects "${objfile}")
- add_custom_command(
- OUTPUT "${objfile}"
- DEPENDS
- ${stdlib_dependencies} "${srcdir}/${module_name_path}.swift"
- ${extra_sources}
- COMMAND "${SWIFT_EXEC}"
- ${common_options}
- "-force-single-frontend-invocation"
- "-parse-as-library"
- "-module-name" "${module_name}"
- "-emit-module" "-emit-module-path" "${swiftmodule}"
- "-o" "${objfile}"
- "${source}" ${extra_sources})
+ add_swift_benchmark_library(objfile_out sibfile_out
+ MODULE_PATH "${module_name_path}"
+ SOURCE_DIR "${srcdir}"
+ OBJECT_DIR "${objdir}"
+ SOURCES ${sources}
+ LIBRARY_FLAGS ${common_options})
+ precondition(objfile_out)
+ list(APPEND bench_library_objects "${objfile_out}")
if (SWIFT_BENCHMARK_EMIT_SIB)
- set(sibfile "${objdir}/${module_name}.sib")
- list(APPEND bench_library_sibfiles "${sibfile}")
- add_custom_command(
- OUTPUT "${sibfile}"
- DEPENDS
- ${stdlib_dependencies} "${srcdir}/${module_name_path}.swift"
- ${extra_sources}
- COMMAND "${SWIFT_EXEC}"
- ${common_options}
- "-force-single-frontend-invocation"
- "-parse-as-library"
- "-module-name" "${module_name}"
- "-emit-sib"
- "-o" "${sibfile}"
- "${source}" ${extra_sources})
+ precondition(sibfile_out)
+ list(APPEND bench_library_sibfiles "${sibfile_out}")
endif()
endforeach()
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 2857478..1727e84 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -1960,6 +1960,23 @@
/// Does this binding declare something that requires storage?
bool hasStorage() const;
+
+ /// Determines whether this binding either has an initializer expression, or is
+ /// default initialized, without performing any type checking on it.
+ ///
+ /// This is only valid to check for bindings which have storage.
+ bool isDefaultInitializable() const {
+ assert(hasStorage());
+
+ for (unsigned i = 0, e = getNumPatternEntries(); i < e; ++i)
+ if (!isDefaultInitializable(i))
+ return false;
+
+ return true;
+ }
+
+ /// Can the pattern at index i be default initialized?
+ bool isDefaultInitializable(unsigned i) const;
/// When the pattern binding contains only a single variable with no
/// destructuring, retrieve that variable.
diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h
index b3ba662..94aba8c 100644
--- a/include/swift/AST/DeclContext.h
+++ b/include/swift/AST/DeclContext.h
@@ -270,12 +270,6 @@
/// Gets the type being declared by this context.
///
- /// - Generic types returns an unbound generic type.
- /// - Non-type contexts returns a null type.
- Type getDeclaredTypeOfContext() const;
-
- /// Gets the type being declared by this context.
- ///
/// - Generic types return a bound generic type using archetypes.
/// - Non-type contexts return a null type.
Type getDeclaredTypeInContext() const;
diff --git a/include/swift/AST/LayoutConstraint.h b/include/swift/AST/LayoutConstraint.h
index b403cdd..ef0561c 100644
--- a/include/swift/AST/LayoutConstraint.h
+++ b/include/swift/AST/LayoutConstraint.h
@@ -150,11 +150,27 @@
return SizeInBits;
}
- unsigned getAlignment() const {
- assert(isKnownSizeTrivial());
+ unsigned getAlignmentInBits() const {
return Alignment;
}
+ unsigned getAlignmentInBytes() const {
+ assert(isKnownSizeTrivial());
+ if (Alignment)
+ return Alignment;
+
+ // There is no explicitly defined alignment. Try to come up with a
+ // reasonable one.
+
+ // If the size is a power of 2, use it also for the default alignment.
+ auto SizeInBytes = getTrivialSizeInBytes();
+ if (llvm::isPowerOf2_32(SizeInBytes))
+ return SizeInBytes * 8;
+
+ // Otherwise assume the alignment of 8 bytes.
+ return 8*8;
+ }
+
operator bool() const {
return isKnownLayout();
}
diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp
index 0191a17..69341f0 100644
--- a/lib/AST/ASTMangler.cpp
+++ b/lib/AST/ASTMangler.cpp
@@ -543,11 +543,10 @@
return DC->isLocalContext();
}
- auto declaredType = DC->getDeclaredTypeOfContext();
- if (!declaredType || declaredType->hasError())
+ auto *nominal = DC->getAsNominalTypeOrNominalTypeExtensionContext();
+ if (nominal == nullptr)
return false;
- auto *nominal = declaredType->getAnyNominal();
if (nominal->getFormalAccess() <= AccessLevel::FilePrivate)
return true;
return isInPrivateOrLocalContext(nominal);
@@ -2043,18 +2042,18 @@
appendOperatorParam("T");
break;
case LayoutConstraintKind::TrivialOfExactSize:
- if (!layout->getAlignment())
+ if (!layout->getAlignmentInBits())
appendOperatorParam("e", Index(layout->getTrivialSizeInBits()));
else
appendOperatorParam("E", Index(layout->getTrivialSizeInBits()),
- Index(layout->getAlignment()));
+ Index(layout->getAlignmentInBits()));
break;
case LayoutConstraintKind::TrivialOfAtMostSize:
- if (!layout->getAlignment())
+ if (!layout->getAlignmentInBits())
appendOperatorParam("m", Index(layout->getTrivialSizeInBits()));
else
appendOperatorParam("M", Index(layout->getTrivialSizeInBits()),
- Index(layout->getAlignment()));
+ Index(layout->getAlignmentInBits()));
break;
}
}
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index 2f8f808..fb6ca10 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -1449,7 +1449,7 @@
bool settable = ASD->isSettable(nullptr);
bool nonmutatingSetter = false;
if (settable && !ASD->isSetterMutating() && ASD->isInstanceMember() &&
- !ASD->getDeclContext()->getDeclaredTypeInContext()
+ !ASD->getDeclContext()->getDeclaredInterfaceType()
->hasReferenceSemantics())
nonmutatingSetter = true;
@@ -2146,10 +2146,10 @@
}
static bool isStructOrClassContext(DeclContext *dc) {
- if (auto ctx = dc->getDeclaredTypeInContext())
- return ctx->getClassOrBoundGenericClass() ||
- ctx->getStructOrBoundGenericStruct();
- return false;
+ auto *nominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
+ if (nominal == nullptr)
+ return false;
+ return isa<ClassDecl>(nominal) || isa<StructDecl>(nominal);
}
static void printParameterFlags(ASTPrinter &printer, PrintOptions options,
@@ -3921,7 +3921,7 @@
Printer << "(";
Printer << SizeInBits;
if (Alignment)
- Printer << ", " << Alignment <<")";
+ Printer << ", " << Alignment;
Printer << ")";
break;
}
diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp
index 384248e..e29a206 100644
--- a/lib/AST/Attr.cpp
+++ b/lib/AST/Attr.cpp
@@ -671,7 +671,7 @@
SourceLoc NameLoc, Identifier Name,
SourceLoc RParenLoc) {
void *mem = Ctx.Allocate(totalSizeToAlloc<SourceLoc>(3), alignof(ObjCAttr));
- return new (mem) ObjCAttr(AtLoc, SourceRange(ObjCLoc),
+ return new (mem) ObjCAttr(AtLoc, SourceRange(ObjCLoc, RParenLoc),
ObjCSelector(Ctx, 0, Name),
SourceRange(LParenLoc, RParenLoc),
NameLoc);
@@ -690,7 +690,7 @@
assert(NameLocs.size() == Names.size());
void *mem = Ctx.Allocate(totalSizeToAlloc<SourceLoc>(NameLocs.size() + 2),
alignof(ObjCAttr));
- return new (mem) ObjCAttr(AtLoc, SourceRange(ObjCLoc),
+ return new (mem) ObjCAttr(AtLoc, SourceRange(ObjCLoc, RParenLoc),
ObjCSelector(Ctx, Names.size(), Names),
SourceRange(LParenLoc, RParenLoc),
NameLocs);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 36d68e9..7bd97a1 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -993,7 +993,7 @@
auto *DC = singleVar->getDeclContext();
if (singleVar->getAttrs().hasAttribute<LazyAttr>() &&
DC->isTypeContext()) {
- bool isInOut = !DC->getDeclaredTypeOfContext()->hasReferenceSemantics();
+ bool isInOut = !DC->getDeclaredInterfaceType()->hasReferenceSemantics();
SelfParam = ParamDecl::createSelf(SourceLoc(), DC,
singleVar->isStatic(),
isInOut);
@@ -1132,6 +1132,94 @@
return nullptr;
}
+/// Check whether the given type representation will be
+/// default-initializable.
+static bool isDefaultInitializable(const TypeRepr *typeRepr) {
+ // Look through most attributes.
+ if (const auto attributed = dyn_cast<AttributedTypeRepr>(typeRepr)) {
+ // Weak ownership implies optionality.
+ if (attributed->getAttrs().getOwnership() == Ownership::Weak)
+ return true;
+
+ return isDefaultInitializable(attributed->getTypeRepr());
+ }
+
+ // Optional types are default-initializable.
+ if (isa<OptionalTypeRepr>(typeRepr) ||
+ isa<ImplicitlyUnwrappedOptionalTypeRepr>(typeRepr))
+ return true;
+
+ // Tuple types are default-initializable if all of their element
+ // types are.
+ if (const auto tuple = dyn_cast<TupleTypeRepr>(typeRepr)) {
+ // ... but not variadic ones.
+ if (tuple->hasEllipsis())
+ return false;
+
+ for (const auto elt : tuple->getElements()) {
+ if (!isDefaultInitializable(elt.Type))
+ return false;
+ }
+
+ return true;
+ }
+
+ // Not default initializable.
+ return false;
+}
+
+// @NSManaged properties never get default initialized, nor do debugger
+// variables and immutable properties.
+bool isNeverDefaultInitializable(const Pattern *p) {
+ bool result = false;
+
+ p->forEachVariable([&](const VarDecl *var) {
+ if (var->getAttrs().hasAttribute<NSManagedAttr>())
+ return;
+
+ if (var->isDebuggerVar() ||
+ var->isLet())
+ result = true;
+ });
+
+ return result;
+}
+
+bool PatternBindingDecl::isDefaultInitializable(unsigned i) const {
+ const auto entry = getPatternList()[i];
+
+ // If it has an initializer expression, this is trivially true.
+ if (entry.getInit())
+ return true;
+
+ if (isNeverDefaultInitializable(entry.getPattern()))
+ return false;
+
+ // If the pattern is typed as optional (or tuples thereof), it is
+ // default initializable.
+ if (const auto typedPattern = dyn_cast<TypedPattern>(entry.getPattern())) {
+ if (const auto typeRepr = typedPattern->getTypeLoc().getTypeRepr()) {
+ if (::isDefaultInitializable(typeRepr))
+ return true;
+ } else if (typedPattern->isImplicit()) {
+ // Lazy vars have implicit storage assigned to back them. Because the
+ // storage is implicit, the pattern is typed and has a TypeLoc, but not a
+ // TypeRepr.
+ //
+ // All lazy storage is implicitly default initializable, though, because
+ // lazy backing storage is optional.
+ if (const auto *varDecl = typedPattern->getSingleVar())
+ // Lazy storage is never user accessible.
+ if (!varDecl->isUserAccessible())
+ if (typedPattern->getTypeLoc().getType()->getAnyOptionalObjectType())
+ return true;
+ }
+ }
+
+ // Otherwise, we can't default initialize this binding.
+ return false;
+}
+
SourceLoc TopLevelCodeDecl::getStartLoc() const {
return Body->getStartLoc();
}
@@ -1350,10 +1438,10 @@
auto *dc = getDeclContext();
if (dc->isTypeContext()) {
- auto declaredType = dc->getDeclaredTypeOfContext();
- if (declaredType->hasError())
+ auto *nominalDecl = dc->getAsNominalTypeOrNominalTypeExtensionContext();
+ if (nominalDecl == nullptr)
return true;
- return declaredType->getAnyNominal()->hasFixedLayout();
+ return nominalDecl->hasFixedLayout();
}
// Private and (unversioned) internal variables always have a
@@ -1731,12 +1819,8 @@
// Dynamic lookup can only find class and protocol members, or extensions of
// classes.
- auto declaredType = getDeclContext()->getDeclaredTypeOfContext();
-
- if (!declaredType)
- return false;
-
- auto nominalDC = declaredType->getAnyNominal();
+ auto nominalDC =
+ getDeclContext()->getAsNominalTypeOrNominalTypeExtensionContext();
if (!nominalDC ||
(!isa<ClassDecl>(nominalDC) && !isa<ProtocolDecl>(nominalDC)))
return false;
@@ -2264,9 +2348,14 @@
DeclContext *dc = decl->getDeclContext();
if (dc->isTypeContext()) {
switch (kind) {
- case DeclTypeKind::DeclaredType:
- Ty = dc->getDeclaredTypeOfContext();
+ case DeclTypeKind::DeclaredType: {
+ auto *nominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
+ if (nominal)
+ Ty = nominal->getDeclaredType();
+ else
+ Ty = ErrorType::get(ctx);
break;
+ }
case DeclTypeKind::DeclaredTypeInContext:
llvm_unreachable("Handled above");
case DeclTypeKind::DeclaredInterfaceType:
@@ -2431,10 +2520,15 @@
UnboundGenericType *TypeAliasDecl::getUnboundGenericType() const {
assert(getGenericParams());
+
+ Type parentTy;
+ auto parentDC = getDeclContext();
+ if (auto nominal = parentDC->getAsNominalTypeOrNominalTypeExtensionContext())
+ parentTy = nominal->getDeclaredType();
+
return UnboundGenericType::get(
const_cast<TypeAliasDecl *>(this),
- getDeclContext()->getDeclaredTypeOfContext(),
- getASTContext());
+ parentTy, getASTContext());
}
Type AbstractTypeParamDecl::getSuperclass() const {
diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp
index 45690b5..27f3d50 100644
--- a/lib/AST/DeclContext.cpp
+++ b/lib/AST/DeclContext.cpp
@@ -147,14 +147,6 @@
llvm_unreachable("Unhandled DeclTypeKind in switch.");
}
-Type DeclContext::getDeclaredTypeOfContext() const {
- if (auto *ED = dyn_cast<ExtensionDecl>(this))
- return computeExtensionType(ED, DeclTypeKind::DeclaredType);
- if (auto *NTD = dyn_cast<NominalTypeDecl>(this))
- return NTD->getDeclaredType();
- return Type();
-}
-
Type DeclContext::getDeclaredTypeInContext() const {
if (auto *ED = dyn_cast<ExtensionDecl>(this))
return computeExtensionType(ED, DeclTypeKind::DeclaredTypeInContext);
@@ -519,7 +511,7 @@
for (const auto *dc = this; dc->isLocalContext(); dc = dc->getParent()) {
// Default argument initializer contexts have their resilience expansion
// set when they're type checked.
- if (auto *DAI = dyn_cast<DefaultArgumentInitializer>(dc)) {
+ if (isa<DefaultArgumentInitializer>(dc)) {
return cast<AbstractFunctionDecl>(dc->getParent())
->getDefaultArgumentResilienceExpansion();
}
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index ed9d420..f0b85ea 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -4568,7 +4568,7 @@
visitPotentialArchetypes([&](PotentialArchetype *archetype) {
if (archetype != archetype->getRepresentative()) return;
- if (auto equivClass = archetype->getEquivalenceClassIfPresent())
+ if (archetype->getEquivalenceClassIfPresent())
checkSameTypeConstraints(genericParams, archetype);
});
diff --git a/lib/AST/LayoutConstraint.cpp b/lib/AST/LayoutConstraint.cpp
index b18b2a0..7062e53 100644
--- a/lib/AST/LayoutConstraint.cpp
+++ b/lib/AST/LayoutConstraint.cpp
@@ -250,12 +250,13 @@
// Check alignments
// Quick exit if at_most_size_layout does not care about the alignment.
- if (!RHS->getAlignment())
+ if (!RHS->getAlignmentInBits())
return LHS;
// Check if fixed_size_layout.alignment is a multiple of
// at_most_size_layout.alignment.
- if (LHS->getAlignment() && LHS->getAlignment() % RHS->getAlignment() == 0)
+ if (LHS->getAlignmentInBits() &&
+ LHS->getAlignmentInBits() % RHS->getAlignmentInBits() == 0)
return LHS;
return LayoutConstraint::getUnknownLayout();
diff --git a/lib/AST/LookupVisibleDecls.cpp b/lib/AST/LookupVisibleDecls.cpp
index 54ad443..cf9e7c3 100644
--- a/lib/AST/LookupVisibleDecls.cpp
+++ b/lib/AST/LookupVisibleDecls.cpp
@@ -722,13 +722,16 @@
Type BaseTy;
const DeclContext *DC;
LazyResolver *TypeResolver;
+ bool IsTypeLookup = false;
OverrideFilteringConsumer(Type BaseTy, const DeclContext *DC,
LazyResolver *resolver)
: BaseTy(BaseTy), DC(DC), TypeResolver(resolver) {
assert(!BaseTy->hasLValueType());
- if (auto *MetaTy = BaseTy->getAs<AnyMetatypeType>())
+ if (auto *MetaTy = BaseTy->getAs<AnyMetatypeType>()) {
BaseTy = MetaTy->getInstanceType();
+ IsTypeLookup = true;
+ }
assert(DC && BaseTy);
}
@@ -781,7 +784,7 @@
// Don't pass UnboundGenericType here. If you see this assertion
// being hit, fix the caller, don't remove it.
- assert(!BaseTy->hasUnboundGenericType());
+ assert(IsTypeLookup || !BaseTy->hasUnboundGenericType());
// If the base type is AnyObject, we might be doing a dynamic
// lookup, so the base type won't match the type of the member's
diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp
index 1979883..718e573 100644
--- a/lib/AST/Module.cpp
+++ b/lib/AST/Module.cpp
@@ -283,10 +283,10 @@
continue;
for (ValueDecl *vd : member.second) {
- Type ty = vd->getDeclContext()->getDeclaredTypeOfContext();
- if (auto nominal = ty->getAnyNominal())
- if (nominal->getName() == accessPath.front().first)
- consumer.foundDecl(vd, DeclVisibilityKind::DynamicLookup);
+ auto *nominal = vd->getDeclContext()
+ ->getAsNominalTypeOrNominalTypeExtensionContext();
+ if (nominal && nominal->getName() == accessPath.front().first)
+ consumer.foundDecl(vd, DeclVisibilityKind::DynamicLookup);
}
}
return;
@@ -318,10 +318,10 @@
if (!accessPath.empty()) {
for (ValueDecl *vd : iter->second) {
- Type ty = vd->getDeclContext()->getDeclaredTypeOfContext();
- if (auto nominal = ty->getAnyNominal())
- if (nominal->getName() == accessPath.front().first)
- results.push_back(vd);
+ auto *nominal = vd->getDeclContext()
+ ->getAsNominalTypeOrNominalTypeExtensionContext();
+ if (nominal && nominal->getName() == accessPath.front().first)
+ results.push_back(vd);
}
return;
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 6cb983d..903d770 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -4033,6 +4033,17 @@
CanType self = getCanonicalType();
+ // Archetypes with a trivial layout constraint can never
+ // represent a class.
+ if (auto Archetype = dyn_cast<ArchetypeType>(self)) {
+ if (auto Layout = Archetype->getLayoutConstraint()) {
+ if (Layout->isTrivial())
+ return TypeTraitResult::IsNot;
+ if (Layout->isClass())
+ return TypeTraitResult::Is;
+ }
+ }
+
// Dependent types might be bound to classes.
if (isa<SubstitutableType>(self))
return TypeTraitResult::CanBe;
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index e539e2b..b4dd301 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -3678,7 +3678,7 @@
ImportedName importedName,
ObjCSelector selector,
bool forceClassMethod) {
- assert(dc->getDeclaredTypeOfContext() && "Method in non-type context?");
+ assert(dc->isTypeContext() && "Method in non-type context?");
assert(isa<ClangModuleUnit>(dc->getModuleScopeContext()) &&
"Clang method in Swift context?");
@@ -5324,7 +5324,7 @@
// instance of the type we're importing onto. Importing this as a method means
// that the method should be treated as mutating in this situation.
bool selfIsInOut = false;
- if (selfIdx && !dc->getDeclaredTypeOfContext()->hasReferenceSemantics()) {
+ if (selfIdx && !dc->getDeclaredInterfaceType()->hasReferenceSemantics()) {
auto selfParam = decl->getParamDecl(*selfIdx);
auto selfParamTy = selfParam->getType();
if ((selfParamTy->isPointerType() || selfParamTy->isReferenceType()) &&
diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp
index 974d49e..ee12bc8 100644
--- a/lib/IDE/CodeCompletion.cpp
+++ b/lib/IDE/CodeCompletion.cpp
@@ -1307,36 +1307,33 @@
auto *DC = CurDeclContext->getInnermostTypeContext();
if (!DC)
return;
- Type DT = DC->getDeclaredTypeOfContext();
- if (DT.isNull() || DT->is<ErrorType>())
+ auto *CD = DC->getAsClassOrClassExtensionContext();
+ if (CD == nullptr)
return;
- Type ST = DT->getSuperclass();
+ Type ST = CD->getSuperclass();
if (ST.isNull() || ST->is<ErrorType>())
return;
- if (ST->getNominalOrBoundGenericNominal()) {
- CodeCompletionResultBuilder Builder(Sink,
- CodeCompletionResult::ResultKind::Keyword,
- SemanticContextKind::CurrentNominal,
- {});
- Builder.setKeywordKind(CodeCompletionKeywordKind::kw_super);
- Builder.addTextChunk("super");
- ST = ST->getReferenceStorageReferent();
- assert(!ST->isVoid() && "Cannot get type name.");
- Builder.addTypeAnnotation(ST.getString());
- }
+
+ CodeCompletionResultBuilder Builder(Sink,
+ CodeCompletionResult::ResultKind::Keyword,
+ SemanticContextKind::CurrentNominal,
+ {});
+ Builder.setKeywordKind(CodeCompletionKeywordKind::kw_super);
+ Builder.addTextChunk("super");
+ Builder.addTypeAnnotation(ST.getString());
}
/// \brief Set to true when we have delivered code completion results
/// to the \c Consumer.
bool DeliveredResults = false;
- bool typecheckContextImpl(DeclContext *DC) {
+ bool typecheckContext(DeclContext *DC) {
// Nothing to type check in module context.
if (DC->isModuleScopeContext())
return true;
// Type check the parent context.
- if (!typecheckContextImpl(DC->getParent()))
+ if (!typecheckContext(DC->getParent()))
return false;
// Type-check this context.
@@ -1373,17 +1370,6 @@
llvm_unreachable("Unhandled DeclContextKind in switch.");
}
- /// \returns true on success, false on failure.
- bool typecheckContext() {
- return typecheckContextImpl(CurDeclContext);
- }
-
- /// \returns true on success, false on failure.
- bool typecheckParsedDecl() {
- assert(ParsedDecl && "should have a parsed decl");
- return typeCheckCompletionDecl(ParsedDecl);
- }
-
Optional<std::pair<Type, ConcreteDeclRef>> typeCheckParsedExpr() {
assert(ParsedExpr && "should have an expression");
@@ -2540,7 +2526,7 @@
}
// If we won't be able to provide a result, bail out.
- if (MemberType->is<ErrorType>() && addName.empty() && !needInit)
+ if (MemberType->hasError() && addName.empty() && !needInit)
return;
// Add the constructor, possibly including any default arguments.
@@ -5118,15 +5104,14 @@
// Add keywords even if type checking fails completely.
addKeywords(CompletionContext.getResultSink(), MaybeFuncBody);
- if (!typecheckContext())
- return;
+ if (auto *DC = dyn_cast_or_null<DeclContext>(ParsedDecl)) {
+ if (DC->isChildContextOf(CurDeclContext))
+ CurDeclContext = DC;
+ }
- if (ParsedDecl && !typecheckParsedDecl())
+ if (!typecheckContext(CurDeclContext))
return;
- if (auto *DC = dyn_cast_or_null<DeclContext>(ParsedDecl))
- CurDeclContext = DC;
-
Optional<Type> ExprType;
ConcreteDeclRef ReferencedDecl = nullptr;
if (ParsedExpr) {
diff --git a/lib/IRGen/GenArchetype.cpp b/lib/IRGen/GenArchetype.cpp
index 4804122..a257fbb 100644
--- a/lib/IRGen/GenArchetype.cpp
+++ b/lib/IRGen/GenArchetype.cpp
@@ -318,7 +318,9 @@
// representation.
if (layout && layout->isFixedSizeTrivial()) {
Size size(layout->getTrivialSizeInBytes());
- Alignment align(layout->getTrivialSizeInBytes());
+ auto layoutAlignment = layout->getAlignmentInBytes();
+ assert(layoutAlignment && "layout constraint alignment should not be 0");
+ Alignment align(layoutAlignment);
auto spareBits =
SpareBitVector::getConstant(size.getValueInBits(), false);
// Get an integer type of the required size.
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 7b6da1c..c63fb59 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -130,7 +130,8 @@
class_replaceMethod = IGM.getClassReplaceMethodFn();
class_addProtocol = IGM.getClassAddProtocolFn();
- CanType origTy = ext->getDeclaredTypeOfContext()->getCanonicalType();
+ CanType origTy = ext->getAsNominalTypeOrNominalTypeExtensionContext()
+ ->getDeclaredType()->getCanonicalType();
classMetadata =
tryEmitConstantHeapMetadataRef(IGM, origTy, /*allowUninit*/ true);
assert(classMetadata &&
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 5fab631..174a627 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -4563,7 +4563,7 @@
NominalTypeDecl *decl,
bool &dependent) {
CanType unboundType
- = decl->getDeclaredTypeOfContext()->getCanonicalType();
+ = decl->getDeclaredType()->getCanonicalType();
dependent = hasDependentValueWitnessTable(IGM, unboundType);
if (dependent)
@@ -4611,7 +4611,7 @@
void addDependentValueWitnessTablePattern() {
emitDependentValueWitnessTablePattern(IGM, B,
- Target->getDeclaredTypeOfContext()->getCanonicalType());
+ Target->getDeclaredType()->getCanonicalType());
}
void emitInitializeMetadata(IRGenFunction &IGF,
@@ -4779,7 +4779,7 @@
void addDependentValueWitnessTablePattern() {
emitDependentValueWitnessTablePattern(IGM, B,
- Target->getDeclaredTypeOfContext()->getCanonicalType());
+ Target->getDeclaredType()->getCanonicalType());
}
void addPayloadSize() {
diff --git a/lib/Index/Index.cpp b/lib/Index/Index.cpp
index 2081613..53c5571 100644
--- a/lib/Index/Index.cpp
+++ b/lib/Index/Index.cpp
@@ -1025,10 +1025,7 @@
}
static NominalTypeDecl *getNominalParent(ValueDecl *D) {
- Type Ty = D->getDeclContext()->getDeclaredTypeOfContext();
- if (!Ty)
- return nullptr;
- return Ty->getAnyNominal();
+ return D->getDeclContext()->getAsNominalTypeOrNominalTypeExtensionContext();
}
bool IndexSwiftASTWalker::initFuncDeclIndexSymbol(FuncDecl *D,
diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp
index 3be2ff5..f9774da 100644
--- a/lib/Index/IndexSymbol.cpp
+++ b/lib/Index/IndexSymbol.cpp
@@ -20,10 +20,7 @@
using namespace swift::index;
static NominalTypeDecl *getNominalParent(const ValueDecl *D) {
- Type Ty = D->getDeclContext()->getDeclaredTypeOfContext();
- if (!Ty)
- return nullptr;
- return Ty->getAnyNominal();
+ return D->getDeclContext()->getAsNominalTypeOrNominalTypeExtensionContext();
}
/// \returns true if \c D is a subclass of 'XCTestCase'.
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index e4f5385..42880bf 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -4846,8 +4846,18 @@
diagnoseWhereClauseInGenericParamList(GenericParams);
+ // Create the decl for the func and add it to the parent scope.
+ auto *FD = FuncDecl::create(Context, StaticLoc, StaticSpelling,
+ FuncLoc, FullName, NameLoc,
+ /*Throws=*/throwsLoc.isValid(), throwsLoc,
+ /*AccessorKeywordLoc=*/SourceLoc(),
+ nullptr, BodyParams, FuncRetTy,
+ CurDeclContext);
+
// Parse a 'where' clause if present, adding it to our GenericParamList.
if (Tok.is(tok::kw_where)) {
+ ContextChange CC(*this, FD);
+
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
@@ -4855,6 +4865,8 @@
return whereStatus;
}
}
+
+ FD->setGenericParams(GenericParams);
// Protocol method arguments may not have default values.
if (Flags.contains(PD_InProtocol) && DefaultArgs.HasDefaultArgument) {
@@ -4870,18 +4882,9 @@
// Enter the arguments for the function into a new function-body scope. We
// need this even if there is no function body to detect argument name
// duplication.
- FuncDecl *FD;
{
Scope S(this, ScopeKind::FunctionBody);
- // Create the decl for the func and add it to the parent scope.
- FD = FuncDecl::create(Context, StaticLoc, StaticSpelling,
- FuncLoc, FullName, NameLoc,
- /*Throws=*/throwsLoc.isValid(), throwsLoc,
- /*AccessorKeywordLoc=*/SourceLoc(),
- GenericParams, BodyParams, FuncRetTy,
- CurDeclContext);
-
diagnoseOperatorFixityAttributes(*this, Attributes, FD);
// Add the attributes here so if we need them while parsing the body
@@ -5016,7 +5019,7 @@
}
EnumDecl *ED = new (Context) EnumDecl(EnumLoc, EnumName, EnumNameLoc,
- { }, GenericParams, CurDeclContext);
+ { }, nullptr, CurDeclContext);
setLocalDiscriminator(ED);
ED->getAttrs() = Attributes;
@@ -5041,9 +5044,10 @@
// Trigger delayed parsing, no need to continue.
return whereStatus;
}
- ED->setGenericParams(GenericParams);
}
+ ED->setGenericParams(GenericParams);
+
SourceLoc LBLoc, RBLoc;
if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_enum)) {
LBLoc = PreviousLoc;
@@ -5277,7 +5281,7 @@
StructDecl *SD = new (Context) StructDecl(StructLoc, StructName,
StructNameLoc,
{ },
- GenericParams,
+ nullptr,
CurDeclContext);
setLocalDiscriminator(SD);
SD->getAttrs() = Attributes;
@@ -5303,9 +5307,10 @@
// Trigger delayed parsing, no need to continue.
return whereStatus;
}
- SD->setGenericParams(GenericParams);
}
-
+
+ SD->setGenericParams(GenericParams);
+
SourceLoc LBLoc, RBLoc;
if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_struct)) {
LBLoc = PreviousLoc;
@@ -5363,7 +5368,7 @@
// Create the class.
ClassDecl *CD = new (Context) ClassDecl(ClassLoc, ClassName, ClassNameLoc,
- { }, GenericParams, CurDeclContext);
+ { }, nullptr, CurDeclContext);
setLocalDiscriminator(CD);
// Attach attributes.
@@ -5390,9 +5395,10 @@
// Trigger delayed parsing, no need to continue.
return whereStatus;
}
- CD->setGenericParams(GenericParams);
}
+ CD->setGenericParams(GenericParams);
+
SourceLoc LBLoc, RBLoc;
if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_class)) {
LBLoc = PreviousLoc;
@@ -5563,8 +5569,20 @@
diagnoseWhereClauseInGenericParamList(GenericParams);
+ // Build an AST for the subscript declaration.
+ DeclName name = DeclName(Context, DeclBaseName::createSubscript(),
+ argumentNames);
+ auto *Subscript = new (Context) SubscriptDecl(name,
+ SubscriptLoc, Indices.get(),
+ ArrowLoc, ElementTy.get(),
+ CurDeclContext,
+ nullptr);
+ Subscript->getAttrs() = Attributes;
+
// Parse a 'where' clause if present, adding it to our GenericParamList.
if (Tok.is(tok::kw_where)) {
+ ContextChange CC(*this, Subscript);
+
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
@@ -5573,15 +5591,7 @@
}
}
- // Build an AST for the subscript declaration.
- DeclName name = DeclName(Context, DeclBaseName::createSubscript(),
- argumentNames);
- auto *Subscript = new (Context) SubscriptDecl(name,
- SubscriptLoc, Indices.get(),
- ArrowLoc, ElementTy.get(),
- CurDeclContext,
- GenericParams);
- Subscript->getAttrs() = Attributes;
+ Subscript->setGenericParams(GenericParams);
// Pass the function signature to code completion.
if (SignatureHasCodeCompletion)
@@ -5690,8 +5700,19 @@
diagnoseWhereClauseInGenericParamList(GenericParams);
+ auto *SelfDecl = ParamDecl::createUnboundSelf(ConstructorLoc, CurDeclContext);
+ DeclName FullName(Context, Context.Id_init, namePieces);
+
+ auto *CD = new (Context) ConstructorDecl(FullName, ConstructorLoc,
+ Failability, FailabilityLoc,
+ throwsLoc.isValid(), throwsLoc,
+ SelfDecl, Params.get(), nullptr,
+ CurDeclContext);
+
// Parse a 'where' clause if present, adding it to our GenericParamList.
if (Tok.is(tok::kw_where)) {
+ ContextChange(*this, CD);
+
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
@@ -5699,18 +5720,10 @@
return whereStatus;
}
}
-
- auto *SelfDecl = ParamDecl::createUnboundSelf(ConstructorLoc, CurDeclContext);
- DeclName FullName(Context, Context.Id_init, namePieces);
+
+ CD->setGenericParams(GenericParams);
Scope S2(this, ScopeKind::ConstructorBody);
- auto *CD = new (Context) ConstructorDecl(FullName, ConstructorLoc,
- Failability, FailabilityLoc,
- throwsLoc.isValid(), throwsLoc,
- SelfDecl, Params.get(),
- GenericParams,
- CurDeclContext);
-
CtorInitializerKind initKind = CtorInitializerKind::Designated;
if (Attributes.hasAttribute<ConvenienceAttr>())
initKind = CtorInitializerKind::Convenience;
diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp
index 7733a2c..f782af6 100644
--- a/lib/SILGen/SILGenConstructor.cpp
+++ b/lib/SILGen/SILGenConstructor.cpp
@@ -354,12 +354,11 @@
}
void SILGenFunction::emitEnumConstructor(EnumElementDecl *element) {
- CanType enumTy = element->getParentEnum()
- ->getDeclaredTypeInContext()
- ->getCanonicalType();
CanType enumIfaceTy = element->getParentEnum()
->getDeclaredInterfaceType()
->getCanonicalType();
+ CanType enumTy = F.mapTypeIntoContext(enumIfaceTy)
+ ->getCanonicalType();
auto &enumTI = getTypeLowering(enumTy);
RegularLocation Loc(element);
diff --git a/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp b/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp
index 6030a07..bce9658 100644
--- a/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp
+++ b/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp
@@ -716,7 +716,7 @@
// TODO: handle cases where a function got smaller.
if ((SILStatsDumpAll &&
(DeltaBlockCount != 0.0 || OldStat.BlockCount == 0)) ||
- (abs(DeltaBlockCount) > FuncBlockCountDeltaThreshold &&
+ (std::abs(DeltaBlockCount) > FuncBlockCountDeltaThreshold &&
OldStat.BlockCount > FuncBlockCountMinThreshold)) {
stats_os() << nl.get();
printCounterChange("function", "block", DeltaBlockCount, OldStat.BlockCount,
@@ -724,7 +724,7 @@
}
if ((SILStatsDumpAll && (DeltaInstCount != 0.0 || OldStat.InstCount == 0)) ||
- (abs(DeltaInstCount) > FuncInstCountDeltaThreshold &&
+ (std::abs(DeltaInstCount) > FuncInstCountDeltaThreshold &&
OldStat.InstCount > FuncInstCountMinThreshold)) {
stats_os() << nl.get();
printCounterChange("function", "inst", DeltaInstCount, OldStat.InstCount,
@@ -760,7 +760,7 @@
if ((SILStatsDumpAll &&
(DeltaBlockCount != 0.0 ||
isFirstTimeData(OldStat.BlockCount, NewStat.BlockCount))) ||
- (abs(DeltaBlockCount) > BlockCountDeltaThreshold)) {
+ (std::abs(DeltaBlockCount) > BlockCountDeltaThreshold)) {
stats_os() << nl.get();
printCounterChange("module", "block", DeltaBlockCount, OldStat.BlockCount,
NewStat.BlockCount, Ctx);
@@ -771,7 +771,7 @@
if ((SILStatsDumpAll &&
(DeltaInstCount != 0.0 ||
isFirstTimeData(OldStat.InstCount, NewStat.InstCount))) ||
- (abs(DeltaInstCount) > InstCountDeltaThreshold)) {
+ (std::abs(DeltaInstCount) > InstCountDeltaThreshold)) {
stats_os() << nl.get();
printCounterChange("module", "inst", DeltaInstCount, OldStat.InstCount,
NewStat.InstCount, Ctx);
@@ -782,7 +782,7 @@
if ((SILStatsDumpAll &&
(DeltaFunctionCount != 0.0 ||
isFirstTimeData(OldStat.FunctionCount, NewStat.FunctionCount))) ||
- (abs(DeltaFunctionCount) > FunctionCountDeltaThreshold)) {
+ (std::abs(DeltaFunctionCount) > FunctionCountDeltaThreshold)) {
stats_os() << nl.get();
printCounterChange("module", "functions", DeltaFunctionCount,
OldStat.FunctionCount, NewStat.FunctionCount, Ctx);
@@ -791,9 +791,9 @@
// Print delta for the used memory only if it is above a threshold or we are
// asked to dump all changes.
if ((SILStatsDumpAll &&
- (abs(DeltaUsedMemory) > UsedMemoryMinDeltaThreshold ||
+ (std::abs(DeltaUsedMemory) > UsedMemoryMinDeltaThreshold ||
isFirstTimeData(OldStat.UsedMemory, NewStat.UsedMemory))) ||
- (abs(DeltaUsedMemory) > UsedMemoryDeltaThreshold)) {
+ (std::abs(DeltaUsedMemory) > UsedMemoryDeltaThreshold)) {
stats_os() << nl.get();
printCounterChange("module", "memory", DeltaUsedMemory, OldStat.UsedMemory,
NewStat.UsedMemory, Ctx);
diff --git a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
index 595de0c..bb78605 100644
--- a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
+++ b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
@@ -621,6 +621,37 @@
return false;
}
+/// Checks if a generic callee and caller have compatible layout constraints.
+static bool isCallerAndCalleeLayoutConstraintsCompatible(FullApplySite AI) {
+ SILFunction *Callee = AI.getReferencedFunction();
+ auto CalleeSig = Callee->getLoweredFunctionType()->getGenericSignature();
+ auto SubstParams = CalleeSig->getSubstitutableParams();
+ auto AISubs = AI.getSubstitutions();
+ for (auto idx : indices(SubstParams)) {
+ auto Param = SubstParams[idx];
+ // Map the parameter into context
+ auto ContextTy = Callee->mapTypeIntoContext(Param->getCanonicalType());
+ auto Archetype = ContextTy->getAs<ArchetypeType>();
+ if (!Archetype)
+ continue;
+ auto Layout = Archetype->getLayoutConstraint();
+ if (!Layout)
+ continue;
+ // The generic parameter has a layout constraint.
+ // Check that the substitution has the same constraint.
+ auto AIReplacement = AISubs[idx].getReplacement();
+ auto AIArchetype = AIReplacement->getAs<ArchetypeType>();
+ if (!AIArchetype)
+ return false;
+ auto AILayout = AIArchetype->getLayoutConstraint();
+ if (!AILayout)
+ return false;
+ if (AILayout != Layout)
+ return false;
+ }
+ return true;
+}
+
// Returns the callee of an apply_inst if it is basically inlineable.
SILFunction *swift::getEligibleFunction(FullApplySite AI,
InlineSelection WhatToInline) {
@@ -725,6 +756,16 @@
return nullptr;
}
+ // We cannot inline function with layout constraints on its generic types
+ // if the corresponding substitution type does not have the same constraints.
+ // The reason for this restriction is that we'd need to be able to express
+ // in SIL something like casting a value of generic type T into a value of
+ // generic type T: _LayoutConstraint, which is impossible currently.
+ if (EnableSILInliningOfGenerics && AI.hasSubstitutions()) {
+ if (!isCallerAndCalleeLayoutConstraintsCompatible(AI))
+ return nullptr;
+ }
+
// IRGen cannot handle partial_applies containing opened_existentials
// in its substitutions list.
if (calleeHasPartialApplyWithOpenedExistentials(AI)) {
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index fc9e7f0..c06fa51 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -710,7 +710,7 @@
// better SILGen.
if (isLValue &&
(isNonMutatingMember(member) ||
- member->getDeclContext()->getDeclaredTypeOfContext()
+ member->getDeclContext()->getDeclaredInterfaceType()
->hasReferenceSemantics())) {
base = cs.coerceToRValue(base);
isLValue = false;
@@ -2480,11 +2480,9 @@
// Determine whether 'super' would have made sense as a base.
bool hasSuper = false;
if (auto func = cs.DC->getInnermostMethodContext()) {
- if (auto nominalType
- = func->getDeclContext()->getDeclaredTypeOfContext()) {
- if (auto classDecl = nominalType->getClassOrBoundGenericClass()) {
- hasSuper = classDecl->hasSuperclass();
- }
+ if (auto classDecl = func->getDeclContext()
+ ->getAsClassOrClassExtensionContext()) {
+ hasSuper = classDecl->hasSuperclass();
}
}
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index eadc66f..bea32ae 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -2754,7 +2754,7 @@
currentTypeContext->getSemanticDepth()) {
diagnose(loc, diag::could_not_use_instance_member_on_type,
currentTypeContext->getDeclaredInterfaceType(), memberName,
- memberTypeContext->getDeclaredTypeOfContext(),
+ memberTypeContext->getDeclaredInterfaceType(),
true)
.highlight(baseRange).highlight(nameLoc.getSourceRange());
} else {
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index a23020c..692dfde 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -2040,11 +2040,13 @@
//
// FIXME: Remove this when lookup of initializers becomes restricted to our
// immediate superclass.
- Type superclassTyInCtor = superclassCtor->getDeclContext()->getDeclaredTypeOfContext();
+ auto *superclassCtorDecl =
+ superclassCtor->getDeclContext()
+ ->getAsNominalTypeOrNominalTypeExtensionContext();
Type superclassTy = classDecl->getSuperclass();
Type superclassTyInContext = classDecl->mapTypeIntoContext(superclassTy);
NominalTypeDecl *superclassDecl = superclassTy->getAnyNominal();
- if (superclassTyInCtor->getAnyNominal() != superclassDecl) {
+ if (superclassCtorDecl != superclassDecl) {
return nullptr;
}
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 0968467..478a588 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -1225,7 +1225,7 @@
// If self is a value type and the base type is an lvalue, wrap it in an
// inout type.
auto selfFlags = ParameterTypeFlags();
- if (!outerDC->getDeclaredTypeOfContext()->hasReferenceSemantics() &&
+ if (!outerDC->getDeclaredInterfaceType()->hasReferenceSemantics() &&
baseTy->is<LValueType>() &&
!selfTy->hasError())
selfFlags = selfFlags.withInOut(true);
diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp
index a0b6b10..8b3d787 100644
--- a/lib/Sema/DerivedConformanceCodable.cpp
+++ b/lib/Sema/DerivedConformanceCodable.cpp
@@ -244,26 +244,19 @@
if (!properties.empty() &&
proto->isSpecificProtocol(KnownProtocolKind::Decodable)) {
for (auto it = properties.begin(); it != properties.end(); ++it) {
+ // If the var is default initializable, then it need not have an explicit
+ // initial value.
auto *varDecl = it->second;
-
- // Optional vars (not lets!) have an implicit default value of nil.
- if (!varDecl->isLet()) {
- if (!varDecl->hasType())
- tc.validateDecl(varDecl);
-
- if (varDecl->hasType()) {
- auto varTypeDecl = varDecl->getType()->getAnyNominal();
- if (varTypeDecl == tc.Context.getOptionalDecl() ||
- varTypeDecl == tc.Context.getImplicitlyUnwrappedOptionalDecl())
- continue;
- }
+ if (auto pbd = varDecl->getParentPatternBinding()) {
+ if (pbd->isDefaultInitializable())
+ continue;
}
- if (varDecl->getParentInitializer() != nullptr) {
- // Var has a default value.
+ if (varDecl->getParentInitializer())
continue;
- }
+ // The var was not default initializable, and did not have an explicit
+ // initial value.
propertiesAreValid = false;
tc.diagnose(it->second->getLoc(), diag::codable_non_decoded_property_here,
proto->getDeclaredType(), it->first);
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index 07ce81e..54fd144 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -2998,7 +2998,9 @@
if (!ctor) return { true, expr };
// Make sure the constructor is within Selector.
- auto ctorContextType = ctor->getDeclContext()->getDeclaredTypeOfContext();
+ auto ctorContextType = ctor->getDeclContext()
+ ->getAsNominalTypeOrNominalTypeExtensionContext()
+ ->getDeclaredType();
if (!ctorContextType || !ctorContextType->isEqual(SelectorTy))
return { true, expr };
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 6b59ab4..9f46093 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -840,88 +840,6 @@
return parentEnv;
}
-/// Check whether the given type representation will be
-/// default-initializable.
-static bool isDefaultInitializable(TypeRepr *typeRepr) {
- // Look through most attributes.
- if (auto attributed = dyn_cast<AttributedTypeRepr>(typeRepr)) {
- // Weak ownership implies optionality.
- if (attributed->getAttrs().getOwnership() == Ownership::Weak)
- return true;
-
- return isDefaultInitializable(attributed->getTypeRepr());
- }
-
- // Optional types are default-initializable.
- if (isa<OptionalTypeRepr>(typeRepr) ||
- isa<ImplicitlyUnwrappedOptionalTypeRepr>(typeRepr))
- return true;
-
- // Tuple types are default-initializable if all of their element
- // types are.
- if (auto tuple = dyn_cast<TupleTypeRepr>(typeRepr)) {
- // ... but not variadic ones.
- if (tuple->hasEllipsis())
- return false;
-
- for (auto elt : tuple->getElements()) {
- if (!isDefaultInitializable(elt.Type))
- return false;
- }
-
- return true;
- }
-
- // Not default initializable.
- return false;
-}
-
-// @NSManaged properties never get default initialized, nor do debugger
-// variables and immutable properties.
-static bool isNeverDefaultInitializable(Pattern *p) {
- bool result = false;
-
- p->forEachVariable([&](VarDecl *var) {
- if (var->getAttrs().hasAttribute<NSManagedAttr>())
- return;
-
- if (var->isDebuggerVar() ||
- var->isLet())
- result = true;
- });
-
- return result;
-}
-
-/// Determine whether the given pattern binding declaration either has
-/// an initializer expression, or is default initialized, without performing
-/// any type checking on it.
-static bool isDefaultInitializable(PatternBindingDecl *pbd) {
- assert(pbd->hasStorage());
-
- for (auto entry : pbd->getPatternList()) {
- // If it has an initializer expression, this is trivially true.
- if (entry.getInit())
- continue;
-
- if (isNeverDefaultInitializable(entry.getPattern()))
- return false;
-
- // If the pattern is typed as optional (or tuples thereof), it is
- // default initializable.
- if (auto typedPattern = dyn_cast<TypedPattern>(entry.getPattern())) {
- if (auto typeRepr = typedPattern->getTypeLoc().getTypeRepr())
- if (isDefaultInitializable(typeRepr))
- continue;
- }
-
- // Otherwise, we can't default initialize this binding.
- return false;
- }
-
- return true;
-}
-
/// Build a default initializer for the given type.
static Expr *buildDefaultInitializer(TypeChecker &tc, Type type) {
// Default-initialize optional types and weak values to 'nil'.
@@ -4225,7 +4143,7 @@
TC.checkTypeModifyingDeclAttributes(var);
// Decide whether we should suppress default initialization.
- if (isNeverDefaultInitializable(PBD->getPattern(i)))
+ if (!PBD->isDefaultInitializable(i))
continue;
auto type = PBD->getPattern(i)->getType();
@@ -4602,7 +4520,7 @@
continue;
if (pbd->isStatic() || !pbd->hasStorage() ||
- isDefaultInitializable(pbd) || pbd->isInvalid())
+ pbd->isDefaultInitializable() || pbd->isInvalid())
continue;
// The variables in this pattern have not been
@@ -8375,8 +8293,8 @@
if (!pbd)
continue;
- if (pbd->isStatic() || !pbd->hasStorage() || isDefaultInitializable(pbd) ||
- pbd->isInvalid())
+ if (pbd->isStatic() || !pbd->hasStorage() ||
+ pbd->isDefaultInitializable() || pbd->isInvalid())
continue;
for (auto entry : pbd->getPatternList()) {
@@ -8504,7 +8422,7 @@
// Complain.
TC.diagnose(insertionLoc, diag::required_initializer_missing,
superInitializer->getFullName(),
- superInitializer->getDeclContext()->getDeclaredTypeOfContext())
+ superInitializer->getDeclContext()->getDeclaredInterfaceType())
.fixItInsert(insertionLoc, initializerText);
TC.diagnose(findNonImplicitRequiredInit(superInitializer),
@@ -8659,7 +8577,7 @@
// If we cannot default initialize the property, we cannot
// synthesize a default initializer for the class.
- if (CheckDefaultInitializer && !isDefaultInitializable(pbd))
+ if (CheckDefaultInitializer && !pbd->isDefaultInitializable())
SuppressDefaultInitializer = true;
}
continue;
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index 4d85138..79badd0 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -1181,7 +1181,7 @@
// Other unused constructor calls.
if (callee && isa<ConstructorDecl>(callee) && !call->isImplicit()) {
diagnose(fn->getLoc(), diag::expression_unused_init_result,
- callee->getDeclContext()->getDeclaredTypeOfContext())
+ callee->getDeclContext()->getDeclaredInterfaceType())
.highlight(call->getArg()->getSourceRange());
return;
}
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 82c443d..44c9f79 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -1174,7 +1174,7 @@
unsigned alignment = 0;
if (layout->isKnownSizeTrivial()) {
size = layout->getTrivialSizeInBits();
- alignment = layout->getAlignment();
+ alignment = layout->getAlignmentInBits();
}
LayoutRequirementKind rawKind = LayoutRequirementKind::UnknownLayout;
switch (layout->getKind()) {
diff --git a/stdlib/public/SDK/Dispatch/Private.swift b/stdlib/public/SDK/Dispatch/Private.swift
index fe0a928..9716834 100644
--- a/stdlib/public/SDK/Dispatch/Private.swift
+++ b/stdlib/public/SDK/Dispatch/Private.swift
@@ -138,7 +138,7 @@
fatalError()
}
-@available(*, unavailable, renamed:"DispatchQueue.apply(attributes:iterations:execute:)")
+@available(*, unavailable, message:"Use DispatchQueue.concurrentPerform(iterations:execute:). The 'queue' argument is not required because the system chooses the appropriate execution context for the block")
public func dispatch_apply(_ iterations: Int, _ queue: DispatchQueue, _ block: (Int) -> Void)
{
fatalError()
diff --git a/stdlib/public/SDK/Dispatch/Time.swift b/stdlib/public/SDK/Dispatch/Time.swift
index 3459d55..721635f 100644
--- a/stdlib/public/SDK/Dispatch/Time.swift
+++ b/stdlib/public/SDK/Dispatch/Time.swift
@@ -114,6 +114,41 @@
}
}
+
+// Returns m1 * m2, clamped to the range [Int64.min, Int64.max].
+// Because of the way this function is used, we can always assume
+// that m2 > 0.
+private func clampedInt64Product(_ m1: Int64, _ m2: Int64) -> Int64 {
+ assert(m2 > 0, "multiplier must be positive")
+ let (result, overflow) = m1.multipliedReportingOverflow(by: m2)
+ if overflow {
+ return m1 > 0 ? Int64.max : Int64.min
+ }
+ return result
+}
+
+// Returns its argument clamped to the range [Int64.min, Int64.max].
+private func toInt64Clamped(_ value: Double) -> Int64 {
+ if value.isNaN { return Int64.max }
+ if value >= Double(Int64.max) { return Int64.max }
+ if value <= Double(Int64.min) { return Int64.min }
+ return Int64(value)
+}
+
+/// Represents a time interval that can be used as an offset from a `DispatchTime`
+/// or `DispatchWallTime`.
+///
+/// For example:
+/// let inOneSecond = DispatchTime.now() + DispatchTimeInterval.seconds(1)
+///
+/// If the requested time interval is larger then the internal representation
+/// permits, the result of adding it to a `DispatchTime` or `DispatchWallTime`
+/// is `DispatchTime.distantFuture` and `DispatchWallTime.distantFuture`
+/// respectively. Such time intervals compare as equal:
+///
+/// let t1 = DispatchTimeInterval.seconds(Int.max)
+/// let t2 = DispatchTimeInterval.milliseconds(Int.max)
+/// let result = t1 == t2 // true
public enum DispatchTimeInterval : Equatable {
case seconds(Int)
case milliseconds(Int)
@@ -124,9 +159,9 @@
internal var rawValue: Int64 {
switch self {
- case .seconds(let s): return Int64(s) * Int64(NSEC_PER_SEC)
- case .milliseconds(let ms): return Int64(ms) * Int64(NSEC_PER_MSEC)
- case .microseconds(let us): return Int64(us) * Int64(NSEC_PER_USEC)
+ case .seconds(let s): return clampedInt64Product(Int64(s), Int64(NSEC_PER_SEC))
+ case .milliseconds(let ms): return clampedInt64Product(Int64(ms), Int64(NSEC_PER_MSEC))
+ case .microseconds(let us): return clampedInt64Product(Int64(us), Int64(NSEC_PER_USEC))
case .nanoseconds(let ns): return Int64(ns)
case .never: return Int64.max
}
@@ -153,16 +188,12 @@
}
public func +(time: DispatchTime, seconds: Double) -> DispatchTime {
- let interval = seconds * Double(NSEC_PER_SEC)
- let t = __dispatch_time(time.rawValue,
- interval.isInfinite || interval.isNaN ? Int64.max : Int64(interval))
+ let t = __dispatch_time(time.rawValue, toInt64Clamped(seconds * Double(NSEC_PER_SEC)));
return DispatchTime(rawValue: t)
}
public func -(time: DispatchTime, seconds: Double) -> DispatchTime {
- let interval = -seconds * Double(NSEC_PER_SEC)
- let t = __dispatch_time(time.rawValue,
- interval.isInfinite || interval.isNaN ? Int64.min : Int64(interval))
+ let t = __dispatch_time(time.rawValue, toInt64Clamped(-seconds * Double(NSEC_PER_SEC)));
return DispatchTime(rawValue: t)
}
@@ -177,15 +208,11 @@
}
public func +(time: DispatchWallTime, seconds: Double) -> DispatchWallTime {
- let interval = seconds * Double(NSEC_PER_SEC)
- let t = __dispatch_time(time.rawValue,
- interval.isInfinite || interval.isNaN ? Int64.max : Int64(interval))
+ let t = __dispatch_time(time.rawValue, toInt64Clamped(seconds * Double(NSEC_PER_SEC)));
return DispatchWallTime(rawValue: t)
}
public func -(time: DispatchWallTime, seconds: Double) -> DispatchWallTime {
- let interval = -seconds * Double(NSEC_PER_SEC)
- let t = __dispatch_time(time.rawValue,
- interval.isInfinite || interval.isNaN ? Int64.min : Int64(interval))
+ let t = __dispatch_time(time.rawValue, toInt64Clamped(-seconds * Double(NSEC_PER_SEC)));
return DispatchWallTime(rawValue: t)
}
diff --git a/test/SILOptimizer/eager_specialize.sil b/test/SILOptimizer/eager_specialize.sil
index d9d66a4..674e125 100644
--- a/test/SILOptimizer/eager_specialize.sil
+++ b/test/SILOptimizer/eager_specialize.sil
@@ -1,6 +1,7 @@
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -eager-specializer %s | %FileCheck %s
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -eager-specializer -sil-deadfuncelim %s | %FileCheck --check-prefix=CHECK-DEADFUNCELIM %s
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -eager-specializer %s -o %t.sil && %target-swift-frontend -assume-parsing-unqualified-ownership-sil -module-name=eager_specialize -emit-ir %t.sil | %FileCheck --check-prefix=CHECK-IRGEN %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -eager-specializer -sil-inline-generics=true -inline %s | %FileCheck --check-prefix=CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE %s
sil_stage canonical
@@ -828,6 +829,27 @@
throw %10 : $Error
} // end sil function '_T034eager_specialize_throwing_function19ClassUsingThrowingPC1gs5Int64VxKAA0G1PRzlFZ'
+// Check that a specialization was produced and it is not inlined.
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE-LABEL: sil{{.*}}@{{.*}}testSimpleGeneric{{.*}}where τ_0_0 : _Trivial(64, 64)
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE-LABEL: sil{{.*}}@testSimpleGeneric :
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE: [[METATYPE:%.*]] = metatype $@thick T.Type
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE: [[SIZEOF:%.*]] = builtin "sizeof"<T>([[METATYPE]] : $@thick T.Type)
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE: [[SIZE:%.*]] = integer_literal $Builtin.Word, 8
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE: builtin "cmp_eq_Word"([[SIZEOF]] : $Builtin.Word, [[SIZE]] : $Builtin.Word)
+// Invoke the specialization, but do not inline it!
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE: function_ref @{{.*}}testSimpleGeneric{{.*}}
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE: apply
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE: // end sil function 'testSimpleGeneric'
+
+sil [_specialize exported: false, kind: full, where T: _Trivial(64, 64)] @testSimpleGeneric : $@convention(thin) <T>(@in T) -> Builtin.Int64 {
+bb0(%0 : $*T):
+ %1 = metatype $@thick T.Type
+ %2 = builtin "sizeof"<T>(%1 : $@thick T.Type) : $Builtin.Word
+ %8 = builtin "zextOrBitCast_Word_Int64"(%2 : $Builtin.Word) : $Builtin.Int64
+ destroy_addr %0 : $*T
+ return %8 : $Builtin.Int64
+}
+
sil_vtable ClassUsingThrowingP {
#ClassUsingThrowingP.init!allocator.1: (ClassUsingThrowingP.Type) -> () -> ClassUsingThrowingP : _T034eager_specialize_throwing_function19ClassUsingThrowingPCACycfC // ClassUsingThrowingP.__allocating_init()
#ClassUsingThrowingP.init!initializer.1: (ClassUsingThrowingP.Type) -> () -> ClassUsingThrowingP : _T034eager_specialize_throwing_function19ClassUsingThrowingPCACycfc // ClassUsingThrowingP.init()
diff --git a/test/SILOptimizer/sil_combine.sil b/test/SILOptimizer/sil_combine.sil
index 6a82113..c97f8b2 100644
--- a/test/SILOptimizer/sil_combine.sil
+++ b/test/SILOptimizer/sil_combine.sil
@@ -859,6 +859,51 @@
return %4 : $Int8 // id: %5
}
+// An archetype with a trivial layout constraint can never be a class.
+// CHECK-LABEL: sil @is_trivial_layout_constraint_class
+sil @is_trivial_layout_constraint_class : $@convention(thin) <T where T: _Trivial> (@in T) -> Int8 {
+bb0(%0 : $*T):
+ %1 = metatype $@thick T.Type
+// CHECK-NOT: builtin "canBeClass"
+// CHECK-NOT: apply
+ %3 = builtin "canBeClass"<T>(%1 : $@thick T.Type) : $Builtin.Int8
+// CHECK: [[LITERAL:%[a-zA-Z0-9]+]] = integer_literal $Builtin.Int8, 0
+// CHECK: [[RESULT:%[a-zA-Z0-9]+]] = struct $Int8 ([[LITERAL]] : $Builtin.Int8)
+ %4 = struct $Int8 (%3 : $Builtin.Int8)
+// CHECK: return [[RESULT]] : $Int8
+ return %4 : $Int8
+}
+
+// An archetype with a _Class layout constraint is always a class.
+// CHECK-LABEL: sil @is_class_layout_constraint_class
+sil @is_class_layout_constraint_class : $@convention(thin) <T where T: _Class> (@in T) -> Int8 {
+bb0(%0 : $*T):
+ %1 = metatype $@thick T.Type
+// CHECK-NOT: builtin "canBeClass"
+// CHECK-NOT: apply
+ %3 = builtin "canBeClass"<T>(%1 : $@thick T.Type) : $Builtin.Int8
+// CHECK: [[LITERAL:%[a-zA-Z0-9]+]] = integer_literal $Builtin.Int8, 1
+// CHECK: [[RESULT:%[a-zA-Z0-9]+]] = struct $Int8 ([[LITERAL]] : $Builtin.Int8)
+ %4 = struct $Int8 (%3 : $Builtin.Int8)
+// CHECK: return [[RESULT]] : $Int8
+ return %4 : $Int8
+}
+
+// An archetype with a _NativeClass layout constraint is always a class.
+// CHECK-LABEL: sil @is_native_class_layout_constraint_class
+sil @is_native_class_layout_constraint_class : $@convention(thin) <T where T: _NativeClass> (@in T) -> Int8 {
+bb0(%0 : $*T):
+ %1 = metatype $@thick T.Type
+// CHECK-NOT: builtin "canBeClass"
+// CHECK-NOT: apply
+ %3 = builtin "canBeClass"<T>(%1 : $@thick T.Type) : $Builtin.Int8
+// CHECK: [[LITERAL:%[a-zA-Z0-9]+]] = integer_literal $Builtin.Int8, 1
+// CHECK: [[RESULT:%[a-zA-Z0-9]+]] = struct $Int8 ([[LITERAL]] : $Builtin.Int8)
+ %4 = struct $Int8 (%3 : $Builtin.Int8)
+// CHECK: return [[RESULT]] : $Int8
+ return %4 : $Int8
+}
+
@objc class MyClass {
}
diff --git a/test/SILOptimizer/string_switch.swift b/test/SILOptimizer/string_switch.swift
index 933c78d..d563a58 100644
--- a/test/SILOptimizer/string_switch.swift
+++ b/test/SILOptimizer/string_switch.swift
@@ -2,6 +2,7 @@
// RUN: %target-build-swift -O %s -module-name=test -Xllvm -sil-disable-pass=FunctionSignatureOpts -emit-sil | %FileCheck %s
// RUN: %target-run %t.out
// UNSUPPORTED: nonatomic_rc
+// UNSUPPORTED: resilient_stdlib
import StdlibUnittest
diff --git a/test/SourceKit/DocumentStructure/structure.swift.response b/test/SourceKit/DocumentStructure/structure.swift.response
index cf78d08..b853950 100644
--- a/test/SourceKit/DocumentStructure/structure.swift.response
+++ b/test/SourceKit/DocumentStructure/structure.swift.response
@@ -50,6 +50,8 @@
key.namelength: 10,
key.attributes: [
{
+ key.offset: 41,
+ key.length: 9,
key.attribute: source.decl.attribute.iboutlet
}
]
@@ -105,6 +107,8 @@
key.bodylength: 5,
key.attributes: [
{
+ key.offset: 136,
+ key.length: 9,
key.attribute: source.decl.attribute.ibaction
}
]
@@ -124,6 +128,8 @@
key.bodylength: 0,
key.attributes: [
{
+ key.offset: 175,
+ key.length: 13,
key.attribute: source.decl.attribute.ibdesignable
}
]
@@ -152,6 +158,8 @@
key.namelength: 17,
key.attributes: [
{
+ key.offset: 221,
+ key.length: 14,
key.attribute: source.decl.attribute.ibinspectable
}
]
@@ -168,6 +176,8 @@
key.namelength: 17,
key.attributes: [
{
+ key.offset: 268,
+ key.length: 14,
key.attribute: source.decl.attribute.gkinspectable
}
]
@@ -938,6 +948,8 @@
],
key.attributes: [
{
+ key.offset: 1406,
+ key.length: 5,
key.attribute: source.decl.attribute.objc
}
],
@@ -961,6 +973,8 @@
key.bodylength: 0,
key.attributes: [
{
+ key.offset: 1449,
+ key.length: 5,
key.attribute: source.decl.attribute.objc
}
]
@@ -985,6 +999,8 @@
],
key.attributes: [
{
+ key.offset: 1474,
+ key.length: 11,
key.attribute: source.decl.attribute.objc.name
}
],
@@ -1008,6 +1024,8 @@
key.bodylength: 0,
key.attributes: [
{
+ key.offset: 1524,
+ key.length: 10,
key.attribute: source.decl.attribute.objc.name
}
]
diff --git a/test/SourceKit/InterfaceGen/gen_clang_module.swift.response b/test/SourceKit/InterfaceGen/gen_clang_module.swift.response
index 800b13c..fec916e 100644
--- a/test/SourceKit/InterfaceGen/gen_clang_module.swift.response
+++ b/test/SourceKit/InterfaceGen/gen_clang_module.swift.response
@@ -5380,6 +5380,8 @@
key.namelength: 21,
key.attributes: [
{
+ key.offset: 3991,
+ key.length: 11,
key.attribute: source.decl.attribute.convenience
}
],
@@ -5975,6 +5977,8 @@
key.namelength: 10,
key.attributes: [
{
+ key.offset: 6061,
+ key.length: 15,
key.attribute: source.decl.attribute.weak
}
]
@@ -5991,6 +5995,8 @@
key.namelength: 16,
key.attributes: [
{
+ key.offset: 6114,
+ key.length: 15,
key.attribute: source.decl.attribute.weak
}
]
@@ -6040,6 +6046,8 @@
key.namelength: 7,
key.attributes: [
{
+ key.offset: 6263,
+ key.length: 4,
key.attribute: source.decl.attribute.weak
}
]
@@ -6091,6 +6099,8 @@
key.namelength: 19,
key.attributes: [
{
+ key.offset: 6390,
+ key.length: 11,
key.attribute: source.decl.attribute.convenience
}
],
@@ -6116,6 +6126,8 @@
key.namelength: 12,
key.attributes: [
{
+ key.offset: 6432,
+ key.length: 39,
key.attribute: source.decl.attribute.available
}
]
@@ -6130,6 +6142,8 @@
key.namelength: 24,
key.attributes: [
{
+ key.offset: 6509,
+ key.length: 23,
key.attribute: source.decl.attribute.available
}
]
@@ -6144,6 +6158,8 @@
key.namelength: 27,
key.attributes: [
{
+ key.offset: 6582,
+ key.length: 47,
key.attribute: source.decl.attribute.available
}
]
@@ -6179,6 +6195,8 @@
],
key.attributes: [
{
+ key.offset: 6703,
+ key.length: 63,
key.attribute: source.decl.attribute.available
}
],
@@ -6285,6 +6303,8 @@
key.namelength: 3,
key.attributes: [
{
+ key.offset: 7094,
+ key.length: 8,
key.attribute: source.decl.attribute.override
}
]
diff --git a/test/SourceKit/InterfaceGen/gen_swift_source.swift.response b/test/SourceKit/InterfaceGen/gen_swift_source.swift.response
index 7834451..537fc33 100644
--- a/test/SourceKit/InterfaceGen/gen_swift_source.swift.response
+++ b/test/SourceKit/InterfaceGen/gen_swift_source.swift.response
@@ -449,6 +449,8 @@
key.namelength: 3,
key.attributes: [
{
+ key.offset: 319,
+ key.length: 8,
key.attribute: source.decl.attribute.override
}
]
diff --git a/test/attr/attr_objc.swift b/test/attr/attr_objc.swift
index 7fe75bd..589dba4 100644
--- a/test/attr/attr_objc.swift
+++ b/test/attr/attr_objc.swift
@@ -204,7 +204,7 @@
case subject_enumElement2
@objc(subject_enumElement3)
- case subject_enumElement3, subject_enumElement4 // expected-error {{'@objc' enum case declaration defines multiple enum cases with the same Objective-C name}}{{3-8=}}
+ case subject_enumElement3, subject_enumElement4 // expected-error {{'@objc' enum case declaration defines multiple enum cases with the same Objective-C name}}{{3-30=}}
@objc // expected-error {{attribute has no effect; cases within an '@objc' enum are already exposed to Objective-C}} {{3-9=}}
case subject_enumElement5, subject_enumElement6
@@ -221,7 +221,7 @@
enum subject_enum2 {
@objc(subject_enum2Element1)
- case subject_enumElement1 // expected-error{{'@objc' enum case is not allowed outside of an '@objc' enum}}{{3-8=}}
+ case subject_enumElement1 // expected-error{{'@objc' enum case is not allowed outside of an '@objc' enum}}{{3-31=}}
}
@objc
@@ -1839,7 +1839,7 @@
}
var prop3: Int {
- @objc(setProperty:) didSet { } // expected-error{{observing accessors are not allowed to be marked @objc}} {{5-10=}}
+ @objc(setProperty:) didSet { } // expected-error{{observing accessors are not allowed to be marked @objc}} {{5-25=}}
}
@objc
diff --git a/test/stdlib/Dispatch.swift b/test/stdlib/Dispatch.swift
index a9a5d81..dbf542f 100644
--- a/test/stdlib/Dispatch.swift
+++ b/test/stdlib/Dispatch.swift
@@ -126,10 +126,24 @@
expectEqual(DispatchTime(uptimeNanoseconds: 1), then)
then = DispatchTime.now() - Double.nan
+ expectEqual(DispatchTime.distantFuture, then)
+
+ then = DispatchTime.now() + Date.distantFuture.timeIntervalSinceNow
+ expectEqual(DispatchTime(uptimeNanoseconds: UInt64.max), then)
+
+ then = DispatchTime.now() + Date.distantPast.timeIntervalSinceNow
expectEqual(DispatchTime(uptimeNanoseconds: 1), then)
+
+ then = DispatchTime.now() - Date.distantFuture.timeIntervalSinceNow
+ expectEqual(DispatchTime(uptimeNanoseconds: 1), then)
+
+ then = DispatchTime.now() - Date.distantPast.timeIntervalSinceNow
+ expectEqual(DispatchTime(uptimeNanoseconds: UInt64.max), then)
}
DispatchAPI.test("DispatchWallTime.addSubtract") {
+ let distantPastRawValue = DispatchWallTime.distantFuture.rawValue - UInt64(1)
+
var then = DispatchWallTime.now() + Double.infinity
expectEqual(DispatchWallTime.distantFuture, then)
@@ -137,10 +151,22 @@
expectEqual(DispatchWallTime.distantFuture, then)
then = DispatchWallTime.now() - Double.infinity
- expectEqual(DispatchWallTime.distantFuture.rawValue - UInt64(1), then.rawValue)
+ expectEqual(distantPastRawValue, then.rawValue)
then = DispatchWallTime.now() - Double.nan
- expectEqual(DispatchWallTime.distantFuture.rawValue - UInt64(1), then.rawValue)
+ expectEqual(DispatchWallTime.distantFuture, then)
+
+ then = DispatchWallTime.now() + Date.distantFuture.timeIntervalSinceNow
+ expectEqual(DispatchWallTime.distantFuture, then)
+
+ then = DispatchWallTime.now() + Date.distantPast.timeIntervalSinceNow
+ expectEqual(distantPastRawValue, then.rawValue)
+
+ then = DispatchWallTime.now() - Date.distantFuture.timeIntervalSinceNow
+ expectEqual(distantPastRawValue, then.rawValue)
+
+ then = DispatchWallTime.now() - Date.distantPast.timeIntervalSinceNow
+ expectEqual(DispatchWallTime.distantFuture, then)
}
DispatchAPI.test("DispatchTime.uptimeNanos") {
@@ -516,6 +542,35 @@
}
}
+DispatchAPI.test("DispatchTimeInterval") {
+ // Basic tests that the correct value is stored and the == method works
+ for i in stride(from:1, through: 100, by: 5) {
+ expectEqual(DispatchTimeInterval.seconds(i), DispatchTimeInterval.milliseconds(i * 1000))
+ expectEqual(DispatchTimeInterval.milliseconds(i), DispatchTimeInterval.microseconds(i * 1000))
+ expectEqual(DispatchTimeInterval.microseconds(i), DispatchTimeInterval.nanoseconds(i * 1000))
+ }
+
+
+ // Check some cases that used to cause arithmetic overflow when evaluating the rawValue for ==
+ var t = DispatchTimeInterval.seconds(Int.max)
+ expectTrue(t == t) // This would crash.
+
+ t = DispatchTimeInterval.seconds(-Int.max)
+ expectTrue(t == t) // This would crash.
+
+ t = DispatchTimeInterval.milliseconds(Int.max)
+ expectTrue(t == t) // This would crash.
+
+ t = DispatchTimeInterval.milliseconds(-Int.max)
+ expectTrue(t == t) // This would crash.
+
+ t = DispatchTimeInterval.microseconds(Int.max)
+ expectTrue(t == t) // This would crash.
+
+ t = DispatchTimeInterval.microseconds(-Int.max)
+ expectTrue(t == t) // This would crash.
+}
+
#if swift(>=4.0)
DispatchAPI.test("DispatchTimeInterval.never.equals") {
expectTrue(DispatchTimeInterval.never == DispatchTimeInterval.never)
diff --git a/test/stdlib/Inputs/ArrayTypesAndHelpers.swift b/test/stdlib/Inputs/ArrayTypesAndHelpers.swift
new file mode 100644
index 0000000..400e730
--- /dev/null
+++ b/test/stdlib/Inputs/ArrayTypesAndHelpers.swift
@@ -0,0 +1,714 @@
+import Swift
+import StdlibUnittest
+#if _runtime(_ObjC)
+import Darwin
+import Foundation
+#endif
+
+
+#if _runtime(_ObjC)
+
+/// Expect some number of autoreleased value objects.
+///
+/// - parameter opt: applies to platforms that have the return-autoreleased
+/// optimization.
+///
+/// - parameter unopt: applies to platforms that don't.
+///
+/// FIXME: Some non-zero `opt` might be cases of missed return-autorelease.
+func expectAutoreleasedValues(
+ opt: Int = 0, unopt: Int = 0) {
+ _expectAutoreleasedKeysAndValues(opt: (0, opt), unopt: (0, unopt))
+}
+
+func isNativeNSArray(_ d: NSArray) -> Bool {
+ let className: NSString = NSStringFromClass(type(of: d)) as NSString
+ return ["_SwiftDeferredNSArray", "_ContiguousArray", "_EmptyArray"].contains {
+ className.range(of: $0).length > 0
+ }
+}
+
+func isCocoaNSArray(_ a: NSArray) -> Bool {
+ let className: NSString = NSStringFromClass(type(of: a)) as NSString
+ return className.range(of: "NSArray").length > 0 ||
+ className.range(of: "NSCFArray").length > 0
+}
+
+func getBridgedNSArrayOfRefTypesBridgedVerbatim() -> NSArray {
+ expectTrue(_isBridgedVerbatimToObjectiveC(TestObjCValueTy.self))
+
+ var a = Array<TestObjCValueTy>()
+ a.reserveCapacity(32)
+ a.append(TestObjCValueTy(1010))
+ a.append(TestObjCValueTy(1020))
+ a.append(TestObjCValueTy(1030))
+
+ let bridged = convertArrayToNSArray(a)
+
+ assert(isNativeNSArray(bridged))
+
+ return bridged
+}
+
+func getBridgedEmptyNSArray() -> NSArray {
+ let a = Array<TestObjCValueTy>()
+
+ let bridged = convertArrayToNSArray(a)
+ assert(isNativeNSArray(bridged))
+
+ return bridged
+}
+
+#endif
+
+func getDerivedAPIsArray() -> Array<Int> {
+ var a = Array<Int>()
+ a.append(1010)
+ a.append(1020)
+ a.append(1030)
+ return a
+}
+
+func _makeExpectedArrayContents(
+ _ expected: [Int]
+) -> [ExpectedArrayElement] {
+ var result = [ExpectedArrayElement]()
+ for value in expected {
+ result.append(ExpectedArrayElement(value: value))
+ }
+ return result
+}
+
+func _equalsWithoutElementIdentity(
+ _ lhs: [ExpectedArrayElement], _ rhs: [ExpectedArrayElement]
+) -> Bool {
+ func stripIdentity(
+ _ list: [ExpectedArrayElement]
+ ) -> [ExpectedArrayElement] {
+ return list.map { ExpectedArrayElement(value: $0.value) }
+ }
+
+ return stripIdentity(lhs).elementsEqual(stripIdentity(rhs))
+}
+
+struct ExpectedArrayElement : Comparable, CustomStringConvertible {
+ var value: Int
+ var valueIdentity: UInt
+
+ init(value: Int, valueIdentity: UInt = 0) {
+ self.value = value
+ self.valueIdentity = valueIdentity
+ }
+
+ var description: String {
+ return "(\(value), \(valueIdentity))"
+ }
+}
+
+func == (
+ lhs: ExpectedArrayElement,
+ rhs: ExpectedArrayElement
+) -> Bool {
+ return
+ lhs.value == rhs.value &&
+ lhs.valueIdentity == rhs.valueIdentity
+}
+
+func < (
+ lhs: ExpectedArrayElement,
+ rhs: ExpectedArrayElement
+) -> Bool {
+ let lhsElements = [ lhs.value, Int(bitPattern: lhs.valueIdentity) ]
+ let rhsElements = [ rhs.value, Int(bitPattern: rhs.valueIdentity) ]
+ return lhsElements.lexicographicallyPrecedes(rhsElements)
+}
+
+#if _runtime(_ObjC)
+ func _checkArrayFastEnumerationImpl(
+ _ expected: [Int],
+ _ a: NSArray,
+ _ makeEnumerator: () -> NSFastEnumeration,
+ _ useEnumerator: (NSArray, NSFastEnumeration, (AnyObject) -> ()) -> Void,
+ _ convertValue: @escaping (AnyObject) -> Int
+) {
+ let expectedContentsWithoutIdentity =
+ _makeExpectedArrayContents(expected)
+
+ var expectedContents = [ExpectedArrayElement]()
+
+ for i in 0..<3 {
+ var actualContents = [ExpectedArrayElement]()
+ let sink = {
+ (value: AnyObject) in
+ actualContents.append(ExpectedArrayElement(
+ value: convertValue(value),
+ valueIdentity: unsafeBitCast(value, to: UInt.self)))
+ }
+
+ useEnumerator(a, makeEnumerator(), sink)
+
+ expectTrue(
+ _equalsWithoutElementIdentity(
+ expectedContentsWithoutIdentity, actualContents),
+ "expected: \(expectedContentsWithoutIdentity)\n" +
+ "actual: \(actualContents)\n")
+
+ if i == 0 {
+ expectedContents = actualContents
+ }
+
+ expectEqualSequence(expectedContents, actualContents)
+ }
+}
+#endif
+
+func getCOWFastArray() -> Array<Int> {
+ var a = Array<Int>()
+ a.reserveCapacity(10)
+ a.append(1)
+ a.append(2)
+ a.append(3)
+ return a
+}
+
+func getCOWSlowArray() -> Array<COWBox<Int>> {
+ var a = Array<COWBox<Int>>()
+ a.reserveCapacity(10)
+ a.append(COWBox(1))
+ a.append(COWBox(2))
+ a.append(COWBox(3))
+ return a
+}
+
+#if _runtime(_ObjC)
+ func slurpFastEnumerationFromObjC(
+ _ a: NSArray, _ fe: NSFastEnumeration, _ sink: (AnyObject) -> Void
+) {
+ let objcValues = NSMutableArray()
+ slurpFastEnumerationOfArrayFromObjCImpl(a, fe, objcValues)
+ for value in objcValues {
+ sink(value as AnyObject)
+ }
+}
+
+import SlurpFastEnumeration
+
+ func slurpFastEnumerationFromSwift(
+ _ a: NSArray, _ fe: NSFastEnumeration, _ sink: (AnyObject) -> Void,
+ maxItems: Int? = nil
+) {
+ var state = NSFastEnumerationState()
+
+ let stackBufLength = 3
+ let stackBuf = _HeapBuffer<(), AnyObject?>(
+ _HeapBufferStorage<(), AnyObject?>.self, (), stackBufLength)
+
+ var itemsReturned = 0
+ while true {
+ let returnedCount = fe.countByEnumerating(
+ with: &state, objects: AutoreleasingUnsafeMutablePointer(stackBuf.baseAddress),
+ count: stackBufLength)
+ expectNotEqual(0, state.state)
+ expectNotNil(state.mutationsPtr)
+ if returnedCount == 0 {
+ break
+ }
+ for i in 0..<returnedCount {
+ let value: AnyObject = state.itemsPtr![i]!
+ sink(value)
+ itemsReturned += 1
+ }
+ if maxItems != nil && itemsReturned >= maxItems! {
+ return
+ }
+ }
+
+ for _ in 0..<3 {
+ let returnedCount = fe.countByEnumerating(
+ with: &state, objects: AutoreleasingUnsafeMutablePointer(stackBuf.baseAddress),
+ count: stackBufLength)
+ expectNotEqual(0, state.state)
+ expectNotNil(state.mutationsPtr)
+ expectEqual(0, returnedCount)
+ }
+}
+
+ func checkArrayFastEnumerationFromSwift(
+ _ expected: [Int],
+ _ a: NSArray, _ makeEnumerator: () -> NSFastEnumeration,
+ _ convertValue: @escaping (AnyObject) -> Int
+) {
+ _checkArrayFastEnumerationImpl(
+ expected, a, makeEnumerator,
+ { (a, fe, sink) in
+ slurpFastEnumerationFromSwift(a, fe, sink)
+ },
+ convertValue)
+}
+
+ func checkArrayFastEnumerationFromObjC(
+ _ expected: [Int],
+ _ a: NSArray, _ makeEnumerator: () -> NSFastEnumeration,
+ _ convertValue: @escaping (AnyObject) -> Int
+) {
+ _checkArrayFastEnumerationImpl(
+ expected, a, makeEnumerator,
+ { (a, fe, sink) in
+ slurpFastEnumerationFromObjC(a, fe, sink)
+ },
+ convertValue)
+}
+
+func getBridgedNSArrayOfObjValue_ValueTypesCustomBridged(
+ numElements: Int = 3
+) -> NSArray {
+ expectFalse(_isBridgedVerbatimToObjectiveC(TestBridgedValueTy.self))
+
+ var a = Array<TestBridgedValueTy>()
+ for i in 1..<(numElements + 1) {
+ a.append(TestBridgedValueTy(i * 10 + 1000))
+ }
+
+ let bridged = convertArrayToNSArray(a)
+ expectTrue(isNativeNSArray(bridged))
+
+ return bridged
+}
+
+ func checkArrayEnumeratorPartialFastEnumerationFromSwift(
+ _ expected: [Int],
+ _ a: NSArray,
+ maxFastEnumerationItems: Int,
+ _ convertValue: @escaping (AnyObject) -> Int
+) {
+ _checkArrayFastEnumerationImpl(
+ expected, a, { a.objectEnumerator() },
+ { (a, fe, sink) in
+ slurpFastEnumerationOfNSEnumeratorFromSwift(
+ a, fe as! NSEnumerator, sink,
+ maxFastEnumerationItems: maxFastEnumerationItems)
+ },
+ convertValue)
+}
+
+ func slurpFastEnumerationOfNSEnumeratorFromSwift(
+ _ a: NSArray, _ enumerator: NSEnumerator, _ sink: (AnyObject) -> Void,
+ maxFastEnumerationItems: Int
+) {
+ slurpFastEnumerationFromSwift(
+ a, enumerator, sink, maxItems: maxFastEnumerationItems)
+ while let value = enumerator.nextObject() {
+ sink(value as AnyObject)
+ }
+}
+
+func _expectAutoreleasedKeysAndValues(
+ opt: (Int, Int) = (0, 0), unopt: (Int, Int) = (0, 0)) {
+ var expectedKeys = 0
+ var expectedValues = 0
+#if arch(i386)
+ (expectedKeys, expectedValues) = unopt
+#else
+ (expectedKeys, expectedValues) = opt
+#endif
+
+ TestObjCValueTy.objectCount -= expectedValues
+}
+
+func isCocoaArray<T>(_ a: Array<T>) -> Bool {
+ return !isNativeArray(a)
+}
+
+func isNativeArray<T>(_ a: Array<T>) -> Bool {
+ return a._buffer._storage.isNative
+}
+
+func convertArrayToNSArray<T>(_ a: [T]) -> NSArray {
+ return a._bridgeToObjectiveC()
+}
+
+func convertNSArrayToArray<T>(_ a: NSArray?) -> [T] {
+ if _slowPath(a == nil) { return [] }
+ var result: [T]?
+ Array._forceBridgeFromObjectiveC(a!, result: &result)
+ return result!
+}
+
+func getAsNSArray(_ a: Array<Int>) -> NSArray {
+ let values = Array(a.map { TestObjCValueTy($0) })
+
+ // Return an `NSMutableArray` to make sure that it has a unique
+ // pointer identity.
+ let nsarray = NSMutableArray()
+ nsarray.addObjects(from: values)
+ return nsarray
+}
+
+func getAsEquatableNSArray(_ a: Array<Int>) -> NSArray {
+ let values = Array(a.map { TestObjCEquatableValueTy($0) })
+
+ // Return an `NSMutableArray` to make sure that it has a unique
+ // pointer identity.
+ let nsarray = NSMutableArray()
+ nsarray.addObjects(from: values)
+ return nsarray
+}
+
+func getAsNSMutableArray(_ a: Array<Int>) -> NSMutableArray {
+ let values = Array(a.map { TestObjCValueTy($0) })
+ let nsarray = NSMutableArray()
+ nsarray.addObjects(from: values)
+ return nsarray
+}
+
+func getBridgedVerbatimArrayAndNSMutableArray()
+ -> (Array<AnyObject>, NSMutableArray) {
+ let nsa = getAsNSMutableArray([1010, 1020, 1030])
+ return (convertNSArrayToArray(nsa), nsa)
+}
+
+func getBridgedVerbatimArray() -> Array<AnyObject> {
+ let nsa = getAsNSArray([1010, 1020, 1030])
+ return convertNSArrayToArray(nsa)
+}
+
+func getBridgedVerbatimArray(_ a: Array<Int>) -> Array<AnyObject> {
+ let nsa = getAsNSArray(a)
+ return convertNSArrayToArray(nsa)
+}
+
+func getBridgedNonverbatimArray() -> Array<TestBridgedValueTy> {
+ let nsa = getAsNSArray([1010, 1020, 1030 ])
+ return Swift._forceBridgeFromObjectiveC(nsa, Array.self)
+}
+
+func getBridgedNonverbatimArray(_ a: Array<Int>) -> Array<TestBridgedValueTy> {
+ let nsa = getAsNSArray(a)
+ return Swift._forceBridgeFromObjectiveC(nsa, Array.self)
+}
+
+func getBridgedNonverbatimArrayAndNSMutableArray()
+ -> (Array<TestBridgedValueTy>, NSMutableArray) {
+ let nsa = getAsNSMutableArray([1010, 1020, 1030])
+ return (Swift._forceBridgeFromObjectiveC(nsa, Array.self), nsa)
+}
+
+func getBridgedVerbatimEquatableArray(_ a: Array<Int>)
+ -> Array<TestObjCEquatableValueTy> {
+ let nsa = getAsEquatableNSArray(a)
+ return convertNSArrayToArray(nsa)
+}
+
+func getBridgedNonverbatimEquatableArray(_ a: Array<Int>)
+ -> Array<TestBridgedEquatableValueTy> {
+ let nsa = getAsEquatableNSArray(a)
+ return Swift._forceBridgeFromObjectiveC(nsa, Array.self)
+}
+
+func getHugeBridgedVerbatimArrayHelper() -> NSArray {
+ let values = (1...32).map { TestObjCValueTy(1000 + $0) }
+
+ let nsa = NSMutableArray()
+ nsa.addObjects(from: values)
+ return nsa
+}
+
+func getHugeBridgedVerbatimArray() -> Array<AnyObject> {
+ let nsa = getHugeBridgedVerbatimArrayHelper()
+ return convertNSArrayToArray(nsa)
+}
+
+func getHugeBridgedNonverbatimArray()
+ -> Array<TestBridgedValueTy> {
+ let nsa = getHugeBridgedVerbatimArrayHelper()
+ return Swift._forceBridgeFromObjectiveC(nsa, Array.self)
+}
+
+func getBridgedNSArrayOfObj_ValueTypeCustomBridged() -> NSArray {
+ expectTrue(_isBridgedVerbatimToObjectiveC(TestObjCValueTy.self))
+
+ var a = Array<TestObjCValueTy>()
+ a.append(TestObjCValueTy(1010))
+ a.append(TestObjCValueTy(1020))
+ a.append(TestObjCValueTy(1030))
+
+ let bridged = convertArrayToNSArray(a)
+ expectTrue(isNativeNSArray(bridged))
+
+ return bridged
+}
+
+func getBridgedNSArrayOfValue_ValueTypeCustomBridged() -> NSArray {
+ expectFalse(_isBridgedVerbatimToObjectiveC(TestBridgedValueTy.self))
+
+ var a = Array<TestBridgedValueTy>()
+ a.append(TestBridgedValueTy(1010))
+ a.append(TestBridgedValueTy(1020))
+ a.append(TestBridgedValueTy(1030))
+
+ let bridged = convertArrayToNSArray(a)
+ expectTrue(isNativeNSArray(bridged))
+
+ return bridged
+}
+
+func getRoundtripBridgedNSArray() -> NSArray {
+ let values = [ 1010, 1020, 1030 ].map { TestObjCValueTy($0) }
+
+ let nsa = NSArray(array: values)
+
+ let a: Array<AnyObject> = convertNSArrayToArray(nsa)
+
+ let bridgedBack = convertArrayToNSArray(a)
+ expectTrue(isCocoaNSArray(bridgedBack))
+ expectEqual(unsafeBitCast(nsa, to: Int.self), unsafeBitCast(bridgedBack, to: Int.self))
+
+ return bridgedBack
+}
+
+var _objcValueCount = _stdlib_AtomicInt(0)
+var _objcValueSerial = _stdlib_AtomicInt(0)
+
+class TestObjCValueTy : NSObject {
+ class var objectCount: Int {
+ get {
+ return _objcValueCount.load()
+ }
+ set {
+ _objcValueCount.store(newValue)
+ }
+ }
+
+ init(_ value: Int) {
+ _objcValueCount.fetchAndAdd(1)
+ serial = _objcValueSerial.addAndFetch(1)
+ self.value = value
+ }
+
+ deinit {
+ assert(serial > 0, "double destruction")
+ _objcValueCount.fetchAndAdd(-1)
+ serial = -serial
+ }
+
+ override var description: String {
+ assert(serial > 0, "dead TestObjCValueTy")
+ return value.description
+ }
+
+ var value: Int
+ var serial: Int
+}
+
+var _objcEquatableValueCount = _stdlib_AtomicInt(0)
+var _objcEquatableValueSerial = _stdlib_AtomicInt(0)
+
+class TestObjCEquatableValueTy : NSObject {
+ class var objectCount: Int {
+ get {
+ return _objcEquatableValueCount.load()
+ }
+ set {
+ _objcEquatableValueCount.store(newValue)
+ }
+ }
+
+ init(_ value: Int) {
+ _objcEquatableValueCount.fetchAndAdd(1)
+ serial = _objcEquatableValueSerial.addAndFetch(1)
+ self.value = value
+ }
+
+ deinit {
+ assert(serial > 0, "double destruction")
+ _objcEquatableValueCount.fetchAndAdd(-1)
+ serial = -serial
+ }
+
+ override func isEqual(_ object: Any!) -> Bool {
+ if let other = object {
+ if let otherObjcKey = other as? TestObjCEquatableValueTy {
+ return self.value == otherObjcKey.value
+ }
+ }
+ return false
+ }
+
+ override var description: String {
+ assert(serial > 0, "dead TestObjCValueTy")
+ return value.description
+ }
+
+ var value: Int
+ var serial: Int
+}
+
+func == (lhs: TestObjCEquatableValueTy, rhs: TestObjCEquatableValueTy) -> Bool {
+ return lhs.value == rhs.value
+}
+
+var _bridgedValueSerial = _stdlib_AtomicInt(0)
+var _bridgedValueBridgeOperations = _stdlib_AtomicInt(0)
+
+struct TestBridgedValueTy : CustomStringConvertible, _ObjectiveCBridgeable {
+ static var bridgeOperations: Int {
+ get {
+ return _bridgedValueBridgeOperations.load()
+ }
+ set {
+ _bridgedValueBridgeOperations.store(newValue)
+ }
+ }
+
+ init(_ value: Int) {
+ serial = _bridgedValueSerial.fetchAndAdd(1)
+ self.value = value
+ }
+
+ var description: String {
+ assert(serial > 0, "dead TestBridgedValueTy")
+ return value.description
+ }
+
+ func _bridgeToObjectiveC() -> TestObjCValueTy {
+ TestBridgedValueTy.bridgeOperations += 1
+ return TestObjCValueTy(value)
+ }
+
+ static func _forceBridgeFromObjectiveC(
+ _ x: TestObjCValueTy,
+ result: inout TestBridgedValueTy?
+ ) {
+ TestBridgedValueTy.bridgeOperations += 1
+ result = TestBridgedValueTy(x.value)
+ }
+
+ static func _conditionallyBridgeFromObjectiveC(
+ _ x: TestObjCValueTy,
+ result: inout TestBridgedValueTy?
+ ) -> Bool {
+ self._forceBridgeFromObjectiveC(x, result: &result)
+ return true
+ }
+
+ static func _unconditionallyBridgeFromObjectiveC(_ source: TestObjCValueTy?)
+ -> TestBridgedValueTy {
+ var result: TestBridgedValueTy? = nil
+ _forceBridgeFromObjectiveC(source!, result: &result)
+ return result!
+ }
+
+ var value: Int
+ var serial: Int
+}
+
+var _bridgedEquatableValueSerial = _stdlib_AtomicInt(0)
+var _bridgedEquatableValueBridgeOperations = _stdlib_AtomicInt(0)
+
+struct TestBridgedEquatableValueTy
+ : Equatable, CustomStringConvertible, _ObjectiveCBridgeable {
+
+ static var bridgeOperations: Int {
+ get {
+ return _bridgedEquatableValueBridgeOperations.load()
+ }
+ set {
+ _bridgedEquatableValueBridgeOperations.store(newValue)
+ }
+ }
+
+ init(_ value: Int) {
+ serial = _bridgedEquatableValueSerial.addAndFetch(1)
+ self.value = value
+ }
+
+ var description: String {
+ assert(serial > 0, "dead TestBridgedValueTy")
+ return value.description
+ }
+
+ func _bridgeToObjectiveC() -> TestObjCEquatableValueTy {
+ _bridgedEquatableValueBridgeOperations.fetchAndAdd(1)
+ return TestObjCEquatableValueTy(value)
+ }
+
+ static func _forceBridgeFromObjectiveC(
+ _ x: TestObjCEquatableValueTy,
+ result: inout TestBridgedEquatableValueTy?
+ ) {
+ _bridgedEquatableValueBridgeOperations.fetchAndAdd(1)
+ result = TestBridgedEquatableValueTy(x.value)
+ }
+
+ static func _conditionallyBridgeFromObjectiveC(
+ _ x: TestObjCEquatableValueTy,
+ result: inout TestBridgedEquatableValueTy?
+ ) -> Bool {
+ self._forceBridgeFromObjectiveC(x, result: &result)
+ return true
+ }
+
+ static func _unconditionallyBridgeFromObjectiveC(
+ _ source: TestObjCEquatableValueTy?
+ ) -> TestBridgedEquatableValueTy {
+ var result: TestBridgedEquatableValueTy? = nil
+ _forceBridgeFromObjectiveC(source!, result: &result)
+ return result!
+ }
+
+ var value: Int
+ var serial: Int
+}
+
+func == (lhs: TestBridgedEquatableValueTy, rhs: TestBridgedEquatableValueTy) -> Bool {
+ return lhs.value == rhs.value
+}
+
+@objc
+class CustomImmutableNSArray : NSArray {
+ init(_privateInit: ()) {
+ super.init()
+ }
+
+ override init() {
+ expectUnreachable()
+ super.init()
+ }
+
+ override init(objects: UnsafePointer<AnyObject>!, count cnt: Int) {
+ expectUnreachable()
+ super.init(objects: objects, count: cnt)
+ }
+
+ required init?(coder aDecoder: NSCoder) {
+ fatalError("init(coder:) not implemented by CustomImmutableNSArray")
+ }
+
+ @objc(copyWithZone:)
+ override func copy(with zone: NSZone?) -> Any {
+ CustomImmutableNSArray.timesCopyWithZoneWasCalled += 1
+ return self
+ }
+
+ override func object(at index: Int) -> Any {
+ CustomImmutableNSArray.timesObjectAtIndexWasCalled += 1
+ return getAsNSArray([1010, 1020, 1030]).object(at: index)
+ }
+
+ override func objectEnumerator() -> NSEnumerator {
+ CustomImmutableNSArray.timesObjectEnumeratorWasCalled += 1
+ return getAsNSArray([1010, 1020, 1030]).objectEnumerator()
+ }
+
+ override var count: Int {
+ CustomImmutableNSArray.timesCountWasCalled += 1
+ return 3
+ }
+
+ static var timesCopyWithZoneWasCalled = 0
+ static var timesObjectAtIndexWasCalled = 0
+ static var timesObjectEnumeratorWasCalled = 0
+ static var timesCountWasCalled = 0
+}
+
+#endif
diff --git a/tools/SourceKit/include/SourceKit/Core/LangSupport.h b/tools/SourceKit/include/SourceKit/Core/LangSupport.h
index c7992e0..7cb7f86 100644
--- a/tools/SourceKit/include/SourceKit/Core/LangSupport.h
+++ b/tools/SourceKit/include/SourceKit/Core/LangSupport.h
@@ -218,7 +218,7 @@
StringRef RuntimeName,
StringRef SelectorName,
ArrayRef<StringRef> InheritedTypes,
- ArrayRef<UIdent> Attrs) = 0;
+ ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) = 0;
virtual bool endDocumentSubStructure() = 0;
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
index 67abda9..94d30e9 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
@@ -1237,7 +1237,27 @@
SmallString<64> SelectorNameBuf;
StringRef SelectorName = getObjCSelectorName(Node.Dcl, SelectorNameBuf);
- std::vector<UIdent> Attrs = SwiftLangSupport::UIDsFromDeclAttributes(Node.Attrs);
+ std::vector<std::tuple<UIdent, unsigned, unsigned>> Attrs;
+
+ for (auto Attr : Node.Attrs) {
+ if (auto AttrUID = SwiftLangSupport::getUIDForDeclAttribute(Attr)) {
+ unsigned AttrOffset = 0;
+ unsigned AttrEnd = 0;
+ auto AttrRange = Attr->getRangeWithAt();
+ if (AttrRange.isValid()) {
+ auto CharRange = Lexer::getCharSourceRangeFromSourceRange(SrcManager,
+ AttrRange);
+ AttrOffset = SrcManager.getLocOffsetInBuffer(CharRange.getStart(),
+ BufferID);
+ AttrEnd = SrcManager.getLocOffsetInBuffer(CharRange.getEnd(),
+ BufferID);
+ }
+
+ auto AttrTuple = std::make_tuple(AttrUID.getValue(), AttrOffset,
+ AttrEnd - AttrOffset);
+ Attrs.push_back(AttrTuple);
+ }
+ }
Consumer.beginDocumentSubStructure(StartOffset, EndOffset - StartOffset,
Kind, AccessLevel, SetterAccessLevel,
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
index 7c719b3..3e7ad81 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
@@ -591,53 +591,37 @@
return swift::ide::NameKind::Swift;
}
-std::vector<UIdent> SwiftLangSupport::UIDsFromDeclAttributes(const DeclAttributes &Attrs) {
- std::vector<UIdent> AttrUIDs;
-
-#define ATTR(X) \
- if (Attrs.has(AK_##X)) { \
- static UIdent Attr_##X("source.decl.attribute."#X); \
- AttrUIDs.push_back(Attr_##X); \
- }
-#include "swift/AST/Attr.def"
-
- for (auto Attr : Attrs) {
- // Check special-case names first.
- switch (Attr->getKind()) {
+Optional<UIdent> SwiftLangSupport::getUIDForDeclAttribute(const swift::DeclAttribute *Attr) {
+ // Check special-case names first.
+ switch (Attr->getKind()) {
case DAK_IBAction: {
static UIdent Attr_IBAction("source.decl.attribute.ibaction");
- AttrUIDs.push_back(Attr_IBAction);
- continue;
+ return Attr_IBAction;
}
case DAK_IBOutlet: {
static UIdent Attr_IBOutlet("source.decl.attribute.iboutlet");
- AttrUIDs.push_back(Attr_IBOutlet);
- continue;
+ return Attr_IBOutlet;
}
case DAK_IBDesignable: {
static UIdent Attr_IBDesignable("source.decl.attribute.ibdesignable");
- AttrUIDs.push_back(Attr_IBDesignable);
- continue;
+ return Attr_IBDesignable;
}
case DAK_IBInspectable: {
static UIdent Attr_IBInspectable("source.decl.attribute.ibinspectable");
- AttrUIDs.push_back(Attr_IBInspectable);
- continue;
+ return Attr_IBInspectable;
}
case DAK_GKInspectable: {
static UIdent Attr_GKInspectable("source.decl.attribute.gkinspectable");
- AttrUIDs.push_back(Attr_GKInspectable);
- continue;
+ return Attr_GKInspectable;
}
case DAK_ObjC: {
static UIdent Attr_Objc("source.decl.attribute.objc");
static UIdent Attr_ObjcNamed("source.decl.attribute.objc.name");
if (cast<ObjCAttr>(Attr)->hasName()) {
- AttrUIDs.push_back(Attr_ObjcNamed);
+ return Attr_ObjcNamed;
} else {
- AttrUIDs.push_back(Attr_Objc);
+ return Attr_Objc;
}
- continue;
}
// We handle access control explicitly.
@@ -647,21 +631,31 @@
case DAK_ShowInInterface:
case DAK_RawDocComment:
case DAK_DowngradeExhaustivityCheck:
- continue;
+ return None;
default:
break;
- }
+ }
- switch (Attr->getKind()) {
+ switch (Attr->getKind()) {
case DAK_Count:
break;
#define DECL_ATTR(X, CLASS, ...)\
case DAK_##CLASS: {\
static UIdent Attr_##X("source.decl.attribute."#X); \
- AttrUIDs.push_back(Attr_##X); \
- break;\
+ return Attr_##X; \
}
#include "swift/AST/Attr.def"
+ }
+
+ return None;
+}
+
+std::vector<UIdent> SwiftLangSupport::UIDsFromDeclAttributes(const DeclAttributes &Attrs) {
+ std::vector<UIdent> AttrUIDs;
+
+ for (auto Attr : Attrs) {
+ if (auto AttrUID = getUIDForDeclAttribute(Attr)) {
+ AttrUIDs.push_back(AttrUID.getValue());
}
}
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
index 656af5d..4e837c1 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
@@ -305,6 +305,8 @@
static SourceKit::UIdent getUIDForRefactoringRangeKind(swift::ide::RefactoringRangeKind Kind);
+ static Optional<UIdent> getUIDForDeclAttribute(const swift::DeclAttribute *Attr);
+
static std::vector<UIdent> UIDsFromDeclAttributes(const swift::DeclAttributes &Attrs);
static SourceKit::UIdent getUIDForNameKind(swift::ide::NameKind Kind);
diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/DocStructureArray.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/DocStructureArray.h
index 6c931c6..a4023ce 100644
--- a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/DocStructureArray.h
+++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/DocStructureArray.h
@@ -38,7 +38,7 @@
llvm::StringRef RuntimeName,
llvm::StringRef SelectorName,
llvm::ArrayRef<llvm::StringRef> InheritedTypes,
- llvm::ArrayRef<SourceKit::UIdent> Attrs);
+ llvm::ArrayRef<std::tuple<SourceKit::UIdent, unsigned, unsigned>> Attrs);
void addElement(SourceKit::UIdent Kind, unsigned Offset, unsigned Length);
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp
index 33d2deb..c03f0d8 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp
@@ -58,7 +58,7 @@
struct DocStructureArrayBuilder::Implementation {
typedef CompactArrayBuilder<StringRef> InheritedTypesBuilder;
SmallVector<char, 256> inheritedTypesBuffer;
- typedef CompactArrayBuilder<UIdent> AttrsBuilder;
+ typedef CompactArrayBuilder<UIdent, unsigned, unsigned> AttrsBuilder;
SmallVector<char, 256> attrsBuffer;
typedef CompactArrayBuilder<UIdent, unsigned, unsigned> ElementsBuilder;
SmallVector<char, 256> elementsBuffer;
@@ -91,7 +91,7 @@
SmallVector<unsigned, 16> topIndices;
unsigned addInheritedTypes(ArrayRef<StringRef> inheritedTypes);
- unsigned addAttrs(ArrayRef<UIdent> attrs);
+ unsigned addAttrs(ArrayRef<std::tuple<UIdent, unsigned, unsigned>> attrs);
unsigned addElements(ArrayRef<Node::Element> elements);
unsigned addChildren(ArrayRef<unsigned> offsets);
@@ -122,13 +122,17 @@
}
unsigned
-DocStructureArrayBuilder::Implementation::addAttrs(ArrayRef<UIdent> attrs) {
+DocStructureArrayBuilder::Implementation::addAttrs(ArrayRef<std::tuple<UIdent, unsigned, unsigned>> attrs) {
if (attrs.empty())
return 0;
AttrsBuilder builder;
- for (UIdent uid : attrs)
- builder.addEntry(uid);
+ for (auto attr : attrs) {
+ UIdent uid;
+ unsigned offset, length;
+ std::tie(uid, offset, length) = attr;
+ builder.addEntry(uid, offset, length);
+ }
unsigned offset = attrsBuffer.size();
builder.appendTo(attrsBuffer);
@@ -174,7 +178,8 @@
unsigned BodyLength, unsigned DocOffset, unsigned DocLength,
StringRef DisplayName, StringRef TypeName,
StringRef RuntimeName, StringRef SelectorName,
- ArrayRef<StringRef> InheritedTypes, ArrayRef<UIdent> Attrs) {
+ ArrayRef<StringRef> InheritedTypes,
+ ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) {
Node node = {
Offset,
@@ -437,7 +442,7 @@
};
struct AttributesReader {
- typedef CompactArrayReader<sourcekitd_uid_t> CompactArrayReaderTy;
+ typedef CompactArrayReader<sourcekitd_uid_t, unsigned, unsigned> CompactArrayReaderTy;
static bool
dictionary_apply(void *buffer, size_t index,
@@ -446,8 +451,13 @@
CompactArrayReaderTy reader(buffer);
sourcekitd_uid_t value;
- reader.readEntries(index, value);
+ unsigned offset;
+ unsigned length;
+ reader.readEntries(index, value, offset, length);
+
APPLY(KeyAttribute, UID, value);
+ APPLY(KeyOffset, Int, offset);
+ APPLY(KeyLength, Int, length);
return true;
}
};
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
index 875b962..f20d429 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
@@ -2000,7 +2000,7 @@
StringRef RuntimeName,
StringRef SelectorName,
ArrayRef<StringRef> InheritedTypes,
- ArrayRef<UIdent> Attrs) override;
+ ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) override;
bool endDocumentSubStructure() override;
@@ -2227,7 +2227,7 @@
StringRef RuntimeName,
StringRef SelectorName,
ArrayRef<StringRef> InheritedTypes,
- ArrayRef<UIdent> Attrs) {
+ ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) {
if (EnableStructure) {
DocStructure.beginSubStructure(
Offset, Length, Kind, AccessLevel, SetterAccessLevel, NameOffset,
diff --git a/tools/SourceKit/utils/buildbot-package-sourcekit.sh b/tools/SourceKit/utils/buildbot-package-sourcekit.sh
deleted file mode 100644
index 282ad6f..0000000
--- a/tools/SourceKit/utils/buildbot-package-sourcekit.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-
-# Make sure the variables and directories we expect to exist actually do.
-test "$WORKSPACE"
-test -d "$WORKSPACE/swift/build"
-test -d "$WORKSPACE/SourceKit/build"
-
-DATE_TAG=`date +%y%m%d%H%M`
-
-mkdir -p SourceKit && cd SourceKit
-mkdir -p bin && mkdir -p lib
-cp "$WORKSPACE/SourceKit/build/bin/sourcekitd-test" bin
-cp "$WORKSPACE/SourceKit/build/bin/sourcekitd-repl" bin
-cp "$WORKSPACE/SourceKit/build/lib/libsourcekitdInProc.dylib" lib
-ditto "$WORKSPACE/SourceKit/build/lib/sourcekitd.framework" lib/sourcekitd.framework
-cp -r "$WORKSPACE/swift/build/lib/swift" lib
-ditto "$WORKSPACE/llvm/build/lib/clang" lib/clang
-cp "$WORKSPACE/llvm/build/lib/libclang.dylib" lib
-install_name_tool -id @rpath/libclang.dylib lib/libclang.dylib
-cd ..
-tar -cvzf SourceKit-$DATE_TAG.tar.gz SourceKit
diff --git a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp
index c947446..fac8a8d 100644
--- a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp
+++ b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp
@@ -59,7 +59,7 @@
StringRef RuntimeName,
StringRef SelectorName,
ArrayRef<StringRef> InheritedTypes,
- ArrayRef<UIdent> Attrs) override {
+ ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) override {
return false;
}
diff --git a/unittests/SourceKit/SwiftLang/EditingTest.cpp b/unittests/SourceKit/SwiftLang/EditingTest.cpp
index 0ba2cb8..7eace92 100644
--- a/unittests/SourceKit/SwiftLang/EditingTest.cpp
+++ b/unittests/SourceKit/SwiftLang/EditingTest.cpp
@@ -64,7 +64,7 @@
StringRef RuntimeName,
StringRef SelectorName,
ArrayRef<StringRef> InheritedTypes,
- ArrayRef<UIdent> Attrs) override {
+ ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) override {
return false;
}
diff --git a/utils/process-stats-dir.py b/utils/process-stats-dir.py
index c9a3425..ac24e0e 100755
--- a/utils/process-stats-dir.py
+++ b/utils/process-stats-dir.py
@@ -20,6 +20,7 @@
import json
import os
import platform
+import re
import sys
import time
import urllib
@@ -154,15 +155,19 @@
return (epoch, value, changed)
-def read_stats_dict_from_csv(f):
+def read_stats_dict_from_csv(f, select_stat=''):
infieldnames = ["epoch", "name", "value"]
c = csv.DictReader(f, infieldnames,
dialect='excel-tab',
quoting=csv.QUOTE_NONNUMERIC)
d = {}
+ sre = re.compile('.*' if len(select_stat) == 0 else
+ '|'.join(select_stat))
for row in c:
epoch = int(row["epoch"])
name = row["name"]
+ if sre.search(name) is None:
+ continue
value = int(row["value"])
update_epoch_value(d, name, epoch, value)
return d
@@ -189,7 +194,8 @@
existing = None
if os.path.exists(args.set_csv_baseline):
with open(args.set_csv_baseline, "r") as f:
- existing = read_stats_dict_from_csv(f)
+ existing = read_stats_dict_from_csv(f,
+ select_stat=args.select_stat)
print ("updating %d baseline entries in %s" %
(len(existing), args.set_csv_baseline))
else:
@@ -273,7 +279,8 @@
def compare_to_csv_baseline(args):
- old_stats = read_stats_dict_from_csv(args.compare_to_csv_baseline)
+ old_stats = read_stats_dict_from_csv(args.compare_to_csv_baseline,
+ select_stat=args.select_stat)
m = merge_all_jobstats((s for d in args.remainder
for s in load_stats_dir(d, **vars(args))),
**vars(args))
@@ -344,7 +351,7 @@
parser.add_argument("--sort-by-delta-pct",
default=False,
action="store_true",
- help="Sort comparison results by delta-%, not stat")
+ help="Sort comparison results by delta-%%, not stat")
parser.add_argument("--sort-descending",
default=False,
action="store_true",
diff --git a/utils/sourcekit_fuzzer/sourcekit_fuzzer.swift b/utils/sourcekit_fuzzer/sourcekit_fuzzer.swift
new file mode 100644
index 0000000..3447451
--- /dev/null
+++ b/utils/sourcekit_fuzzer/sourcekit_fuzzer.swift
@@ -0,0 +1,195 @@
+// --- sourcekit_fuzzer.swift - a simple code completion fuzzer ---------------
+//
+// 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
+//
+// ----------------------------------------------------------------------------
+//
+// The idea here is we start with a source file and proceed to place the cursor
+// at random locations in the file, eventually visiting all locations exactly
+// once in a shuffled random order.
+//
+// If completion at a location crashes, we run the test case through 'creduce'
+// to find a minimal reproducer that also crashes (possibly with a different
+// crash, but in practice all the examples I've seen continue to crash in the
+// same way as creduce performs its reduction).
+//
+// Once creduce fully reduces a test case, we save it to a file named
+// 'crash-NNN.swift', with a RUN: line suitable for placing the test case in
+// 'validation-tests/IDE/crashers_2'.
+//
+// The overall script execution stops once all source locations in the file
+// have been tested.
+//
+// You must first install creduce <https://embed.cs.utah.edu/creduce/>
+// somewhere in your $PATH. Then, run this script as follows:
+//
+// swift utils/sourcekit_fuzzer/sourcekit_fuzzer.swift <build dir> <source file>
+//
+// - <build dir> is your Swift build directory (the one with subdirectories
+// named swift-macosx-x86_64 and llvm-macosx-x86_64).
+//
+// - <source file> is the source file to fuzz. Try any complex but
+// self-contained Swift file that exercises a variety of language features;
+// for example, I've had good results with the files in test/Prototypes/.
+//
+// TODO:
+// - Add fuzzing for CursorInfo and RangeInfo
+// - Get it running on Linux
+// - Better error handling
+// - More user-friendly output
+
+import Darwin
+import Foundation
+
+// https://stackoverflow.com/questions/24026510/how-do-i-shuffle-an-array-in-swift/24029847
+extension MutableCollection {
+ /// Shuffles the contents of this collection.
+ mutating func shuffle() {
+ let c = count
+ guard c > 1 else { return }
+
+ for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
+ let d: IndexDistance = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
+ guard d != 0 else { continue }
+ let i = index(firstUnshuffled, offsetBy: d)
+ swapAt(firstUnshuffled, i)
+ }
+ }
+}
+
+extension String {
+ func write(to path: String) throws {
+ try write(to: URL(fileURLWithPath: path), atomically: true, encoding: String.Encoding.utf8)
+ }
+}
+
+// Gross
+enum ProcessError : Error {
+ case failed
+}
+
+func run(_ args: [String]) throws -> Int32 {
+ var pid: pid_t = 0
+
+ let argv = args.map {
+ $0.withCString(strdup)
+ }
+ defer { argv.forEach { free($0) } }
+
+ let envp = ProcessInfo.processInfo.environment.map {
+ "\($0.0)=\($0.1)".withCString(strdup)
+ }
+ defer { envp.forEach { free($0) } }
+
+ let result = posix_spawn(&pid, argv[0], nil, nil, argv + [nil], envp + [nil])
+ if result != 0 { throw ProcessError.failed }
+
+ var stat: Int32 = 0
+ waitpid(pid, &stat, 0)
+
+ return stat
+}
+
+var arguments = CommandLine.arguments
+
+// Workaround for behavior of CommandLine in script mode, where we don't drop
+// the filename argument from the list.
+if arguments.first == "sourcekit_fuzzer.swift" {
+ arguments = Array(arguments[1...])
+}
+
+if arguments.count != 2 {
+ print("Usage: sourcekit_fuzzer <build directory> <file>")
+ exit(1)
+}
+
+let buildDir = arguments[0]
+
+let notPath = "\(buildDir)/llvm-macosx-x86_64/bin/not"
+let swiftIdeTestPath = "\(buildDir)/swift-macosx-x86_64/bin/swift-ide-test"
+let creducePath = "/usr/local/bin/creduce"
+
+let file = arguments[1]
+
+let contents = try! String(contentsOfFile: file)
+
+var offsets = Array(0...contents.count)
+offsets.shuffle()
+
+var good = 0
+var bad = 0
+
+for offset in offsets {
+ print("TOTAL FAILURES: \(bad) out of \(bad + good)")
+
+ let index = contents.index(contents.startIndex, offsetBy: offset)
+ let prefix = contents[..<index]
+ let suffix = contents[index...]
+ let newContents = String(prefix + "#^A^#" + suffix)
+
+ let sourcePath = "out\(offset).swift"
+ try! newContents.write(to: sourcePath)
+
+ let shellScriptPath = "out\(offset).sh"
+ let shellScript = """
+ #!/bin/sh
+ \(notPath) --crash \(swiftIdeTestPath) -code-completion -code-completion-token=A -source-filename=\(sourcePath)
+ """
+ try! shellScript.write(to: shellScriptPath)
+
+ defer {
+ unlink(shellScriptPath)
+ unlink(sourcePath)
+ }
+
+ do {
+ let result = chmod(shellScriptPath, 0o700)
+ if result != 0 {
+ print("chmod failed")
+ exit(1)
+ }
+ }
+
+ do {
+ let result = try! run(["./\(shellScriptPath)"])
+ if result != 0 {
+ good += 1
+ continue
+ }
+ }
+
+ do {
+ // Because we invert the exit code with 'not', an exit code for 0 actually
+ // indicates failure
+ print("Failed at offset \(offset)")
+ print("Reducing...")
+
+ let result = try! run([creducePath, shellScriptPath, sourcePath])
+ if result != 0 {
+ print("creduce failed")
+ exit(1)
+ }
+
+ bad += 1
+ }
+
+ do {
+ let reduction = try! String(contentsOfFile: sourcePath)
+
+ let testcasePath = "crash-\(bad).swift"
+ let testcase = """
+ // RUN: \(notPath) --crash \(swiftIdeTestPath) -code-completion -code-completion-token=A -source-filename=%s
+ // REQUIRES: asserts
+
+ \(reduction)
+ """
+
+ try! testcase.write(to: testcasePath)
+ }
+}
diff --git a/utils/type-layout-fuzzer.py b/utils/type-layout-fuzzer.py
new file mode 100644
index 0000000..bb3d8c3
--- /dev/null
+++ b/utils/type-layout-fuzzer.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+
+# This script outputs a Swift source with randomly-generated type definitions,
+# which can be used for ABI or layout algorithm fuzzing.
+
+# TODO: generate types with generics, existentials, compositions
+
+from __future__ import print_function
+
+import random
+import sys
+
+maxDepth = 5
+maxMembers = 5
+typesDefined = []
+classesDefined = []
+nextToDefine = 0
+objcInterop = False
+
+if len(sys.argv) >= 2:
+ if sys.argv[1] == "--objc":
+ objcInterop = True
+ if sys.argv[1] == "--help":
+ print("Usage: " + sys.argv[0] + " [--objc]", file=sys.stderr)
+ print("", file=sys.stderr)
+ print(" --objc Include ObjC-interop types", file=sys.stderr)
+ sys.exit(2)
+
+random.seed()
+if objcInterop:
+ print("import Foundation")
+ print()
+
+
+def randomTypeList(depth):
+ count = random.randint(0, maxMembers)
+ result = "("
+ for i in xrange(count):
+ if i > 0:
+ result += ", "
+ result += randomTypeReference(depth + 1)
+ result += ")"
+ return result
+
+
+def randomTypeReference(depth):
+ def nominal():
+ global typesDefined
+ allowNew = depth < maxDepth
+ bound = len(classesDefined) if allowNew else len(classesDefined) - 1
+ which = random.randint(0, bound)
+ if which < len(classesDefined):
+ return classesDefined[which]
+ newName = "T" + str(len(typesDefined))
+
+ def defineRandomRelatedType(name):
+ defineRandomNominalType(name, depth)
+
+ typesDefined.append((newName, defineRandomRelatedType))
+ return newName
+
+ def tuple():
+ return randomTypeList(depth + 1)
+
+ def metatype():
+ return "(" + randomTypeReference(depth + 1) + ").Type"
+
+ def leaf():
+ leaves = ["Int", "String", "Int8", "Int16", "Int32", "Int64",
+ "(() -> ())", "(@convention(c) () -> ())", "AnyObject"]
+ if objcInterop:
+ leaves += ["NSObject", "(@convention(block) () -> ())"]
+ return random.choice(leaves)
+
+ if depth < maxDepth:
+ kinds = [nominal, tuple, metatype, leaf, leaf, leaf, leaf, leaf]
+ else:
+ kinds = [leaf]
+ return random.choice(kinds)()
+
+
+def defineRandomFields(depth, basename):
+ numMembers = random.randint(0, maxMembers)
+ for i in xrange(numMembers):
+ print(" var " + basename + str(i) + ": " +
+ randomTypeReference(depth + 1))
+
+
+def defineRandomClass(name, depth):
+ global classesDefined
+ classesDefined.append(name)
+ print("class " + name, end="")
+
+ def inheritNSObject():
+ print(": NSObject", end="")
+
+ def inheritsOtherClass():
+ print(": ", end="")
+ name = "T" + str(len(typesDefined))
+
+ def defineRandomBaseClass(name):
+ defineRandomClass(name, depth)
+
+ typesDefined.append((name, defineRandomBaseClass))
+ print(name, end="")
+
+ def inheritsNothing():
+ pass
+
+ inheritances = [inheritsNothing]
+ if depth == 0:
+ # The contents of classes are interesting only for top-level type
+ inheritances += [inheritsOtherClass]
+
+ if objcInterop:
+ inheritances += [inheritNSObject]
+ random.choice(inheritances)()
+
+ print(" {")
+ # Prevent errors about lack of initializers
+ print(" init(" + name + ": ()) { fatalError() }")
+ # The contents of classes are interesting only for top-level type
+ if depth == 0:
+ defineRandomFields(depth, "x" + name)
+ print("}")
+ print()
+
+
+def defineRandomNominalType(name, depth=0):
+ def struct():
+ print("struct " + name + " {")
+ defineRandomFields(depth, "x")
+ print("}")
+ print()
+
+ def clas():
+ defineRandomClass(name, depth)
+
+ def enum():
+ # TODO: indirect cases
+ print("enum " + name + " {")
+
+ numCases = random.randint(0, maxMembers)
+ for i in xrange(numCases):
+ print(" case x" + str(i) + randomTypeList(depth + 1))
+
+ print("}")
+ print()
+
+ kinds = [struct, clas, enum]
+ return random.choice(kinds)()
+
+
+typesDefined.append(("Generated", defineRandomNominalType))
+
+while nextToDefine < len(typesDefined):
+ name, definer = typesDefined[nextToDefine]
+ definer(name)
+ nextToDefine += 1
diff --git a/validation-test/IDE/crashers_2/0002-complete-unbound-generic-type.swift b/validation-test/IDE/crashers_2/0002-complete-unbound-generic-type.swift
deleted file mode 100644
index 392dc02..0000000
--- a/validation-test/IDE/crashers_2/0002-complete-unbound-generic-type.swift
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
-// REQUIRES: asserts
-
-let bounds: Range#^A^#
diff --git a/validation-test/IDE/crashers_2/0003-complete-default-argument-closure.swift b/validation-test/IDE/crashers_2/0003-complete-default-argument-closure.swift
deleted file mode 100644
index 0492b75..0000000
--- a/validation-test/IDE/crashers_2/0003-complete-default-argument-closure.swift
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
-// REQUIRES: asserts
-
-func searchTest(format: ()->String = { "" }#^A^#) {}
diff --git a/validation-test/IDE/crashers_2/0011-complete-protocol-with-initializer.swift b/validation-test/IDE/crashers_2/0015-pound-if-without-endif.swift
similarity index 90%
rename from validation-test/IDE/crashers_2/0011-complete-protocol-with-initializer.swift
rename to validation-test/IDE/crashers_2/0015-pound-if-without-endif.swift
index 15d2940..941f317 100644
--- a/validation-test/IDE/crashers_2/0011-complete-protocol-with-initializer.swift
+++ b/validation-test/IDE/crashers_2/0015-pound-if-without-endif.swift
@@ -1,4 +1,5 @@
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
// REQUIRES: asserts
-Integer#^A^#
+#if a
+#^A^#
diff --git a/validation-test/IDE/crashers_2/0011-complete-protocol-with-initializer.swift b/validation-test/IDE/crashers_2/0016-operator-unresolved-dot.swift
similarity index 73%
copy from validation-test/IDE/crashers_2/0011-complete-protocol-with-initializer.swift
copy to validation-test/IDE/crashers_2/0016-operator-unresolved-dot.swift
index 15d2940..aaadffe 100644
--- a/validation-test/IDE/crashers_2/0011-complete-protocol-with-initializer.swift
+++ b/validation-test/IDE/crashers_2/0016-operator-unresolved-dot.swift
@@ -1,4 +1,4 @@
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
// REQUIRES: asserts
-Integer#^A^#
+struct a { func b(c d: a) { b(c: d) == .#^A^#
diff --git a/validation-test/IDE/crashers_2_fixed/0002-complete-unbound-generic-type.swift b/validation-test/IDE/crashers_2_fixed/0002-complete-unbound-generic-type.swift
new file mode 100644
index 0000000..48bdf3a
--- /dev/null
+++ b/validation-test/IDE/crashers_2_fixed/0002-complete-unbound-generic-type.swift
@@ -0,0 +1,3 @@
+// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
+
+let bounds: Range#^A^#
diff --git a/validation-test/IDE/crashers_2_fixed/0003-complete-default-argument-closure.swift b/validation-test/IDE/crashers_2_fixed/0003-complete-default-argument-closure.swift
new file mode 100644
index 0000000..7438f2c
--- /dev/null
+++ b/validation-test/IDE/crashers_2_fixed/0003-complete-default-argument-closure.swift
@@ -0,0 +1,3 @@
+// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
+
+func searchTest(format: ()->String = { "" }#^A^#) {}
diff --git a/validation-test/IDE/crashers_2_fixed/0011-complete-protocol-with-initializer.swift b/validation-test/IDE/crashers_2_fixed/0011-complete-protocol-with-initializer.swift
new file mode 100644
index 0000000..02f1aeb
--- /dev/null
+++ b/validation-test/IDE/crashers_2_fixed/0011-complete-protocol-with-initializer.swift
@@ -0,0 +1,3 @@
+// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
+
+Integer#^A^#
diff --git a/validation-test/compiler_crashers/28837-swift-protocolcompositiontype-get-swift-astcontext-const-llvm-arrayref-swift-typ.swift b/validation-test/compiler_crashers/28837-swift-protocolcompositiontype-get-swift-astcontext-const-llvm-arrayref-swift-typ.swift
new file mode 100644
index 0000000..bc45c00
--- /dev/null
+++ b/validation-test/compiler_crashers/28837-swift-protocolcompositiontype-get-swift-astcontext-const-llvm-arrayref-swift-typ.swift
@@ -0,0 +1,10 @@
+// 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
+
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+protocol b:Self.a&(Int
+protocol b{}
diff --git a/validation-test/compiler_crashers/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift b/validation-test/compiler_crashers/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
new file mode 100644
index 0000000..93668fb
--- /dev/null
+++ b/validation-test/compiler_crashers/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
@@ -0,0 +1,12 @@
+// 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
+
+// REQUIRES: asserts
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+protocol P{typealias e:A
+protocol A:P{}typealias a
+class a<a
diff --git a/validation-test/compiler_crashers/28839-genericsig.swift b/validation-test/compiler_crashers/28839-genericsig.swift
new file mode 100644
index 0000000..0e6d692
--- /dev/null
+++ b/validation-test/compiler_crashers/28839-genericsig.swift
@@ -0,0 +1,12 @@
+// 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
+
+// REQUIRES: asserts
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+class a{
+class a<a:A
+protocol A:a{typealias wh:Self.a
diff --git a/validation-test/compiler_crashers/28840-swift-typebase-getcanonicaltype.swift b/validation-test/compiler_crashers/28840-swift-typebase-getcanonicaltype.swift
new file mode 100644
index 0000000..0222a22
--- /dev/null
+++ b/validation-test/compiler_crashers/28840-swift-typebase-getcanonicaltype.swift
@@ -0,0 +1,9 @@
+// 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
+
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+protocol P{{}typealias a=(t:Self.a{}typealias a:a
diff --git a/validation-test/stdlib/Arrays.swift.gyb b/validation-test/stdlib/Arrays.swift.gyb
index fd7c6ad..38c3e5a 100644
--- a/validation-test/stdlib/Arrays.swift.gyb
+++ b/validation-test/stdlib/Arrays.swift.gyb
@@ -1,9 +1,25 @@
-// RUN: %target-run-simple-swiftgyb
+// RUN: %empty-directory(%t)
+//
+// RUN: %gyb %s -o %t/main.swift
+// RUN: if [ %target-runtime == "objc" ]; then \
+// RUN: %target-clang -fobjc-arc %S/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m -c -o %t/SlurpFastEnumeration.o; \
+// RUN: %line-directive %t/main.swift -- %target-build-swift %t/main.swift %S/Inputs/ArrayTypesAndHelpers.swift -I %S/Inputs/SlurpFastEnumeration/ -Xlinker %t/SlurpFastEnumeration.o -o %t/Arrays -Xfrontend -disable-access-control; \
+// RUN: else \
+// RUN: %line-directive %t/main.swift -- %target-build-swift %S/Inputs/ArrayTypesAndHelpers.swift %t/main.swift -o %t/Arrays -Xfrontend -disable-access-control; \
+// RUN: fi
+//
+// RUN: %line-directive %t/main.swift -- %target-run %t/Arrays
// REQUIRES: executable_test
+import Swift
import StdlibUnittest
import StdlibCollectionUnittest
+#if _runtime(_ObjC)
+import Foundation
+import StdlibUnittestFoundationExtras
+#endif
+
let CopyToNativeArrayBufferTests = TestSuite("CopyToNativeArrayBufferTests")
extension Array {
@@ -97,6 +113,1381 @@
}
}
+ArrayTestSuite.test("capacity/reserveCapacity(_:)") {
+ var a1 = [1010, 1020, 1030]
+ expectGE(a1.capacity, 3)
+ a1.append(1040)
+ expectGT(a1.capacity, 3)
+
+ // Reserving new capacity jumps up to next limit.
+ a1.reserveCapacity(7)
+ expectGE(a1.capacity, 7)
+
+ // Can reserve right up to a limit.
+ a1.reserveCapacity(24)
+ expectGE(a1.capacity, 24)
+
+ // Fill up to the limit, no reallocation.
+ for v in stride(from: 50, through: 240, by: 10).lazy.map({ 1000 + $0 }) {
+ a1.append(v)
+ }
+ expectEqual(24, a1.count)
+ expectGE(a1.capacity, 24)
+ a1.append(1250)
+ expectGT(a1.capacity, 24)
+}
+
+ArrayTestSuite.test("init(arrayLiteral:)") {
+ do {
+ let empty = Array<Int>()
+ expectEqual(0, empty.count)
+ }
+ do {
+ let a = Array(arrayLiteral: 1010)
+ expectEqual(1, a.count)
+ expectEqual(1010, a[0])
+ }
+ do {
+ let a = Array(arrayLiteral: 1010, 1020)
+ expectEqual(2, a.count)
+ expectEqual(1010, a[0])
+ expectEqual(1020, a[1])
+ }
+ do {
+ let a = Array(arrayLiteral: 1010, 1020, 1030)
+ expectEqual(3, a.count)
+ expectEqual(1010, a[0])
+ expectEqual(1020, a[1])
+ expectEqual(1030, a[2])
+ }
+ do {
+ let a = Array(arrayLiteral: 1010, 1020, 1030, 1040)
+ expectEqual(4, a.count)
+ expectEqual(1010, a[0])
+ expectEqual(1020, a[1])
+ expectEqual(1030, a[2])
+ expectEqual(1040, a[3])
+ }
+ do {
+ let a: Array<Int> = [ 1010, 1020, 1030 ]
+ expectEqual(3, a.count)
+ expectEqual(1010, a[0])
+ expectEqual(1020, a[1])
+ expectEqual(1030, a[2])
+ }
+}
+
+ArrayTestSuite.test("init(repeating:count:)") {
+ do {
+ let a = Array(repeating: 1010, count: 5)
+ expectEqual(a.count, 5)
+ expectEqual(1010, a[0])
+ expectEqual(1010, a[1])
+ expectEqual(1010, a[2])
+ expectEqual(1010, a[3])
+ expectEqual(1010, a[4])
+ }
+}
+
+#if _runtime(_ObjC)
+//===----------------------------------------------------------------------===//
+// NSArray -> Array bridging tests.
+//===----------------------------------------------------------------------===//
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.ArrayIsCopied") {
+ var (a, nsa) = getBridgedVerbatimArrayAndNSMutableArray()
+ expectTrue(isCocoaArray(a))
+
+ // Find an existing value.
+ do {
+ let v = a[0] as! TestObjCValueTy
+ expectEqual(1010, v.value)
+ }
+
+ // Remove the value from the NSMutableArray.
+ nsa.removeObject(at: 0)
+
+ // Find an existing value, again.
+ do {
+ let v = a[0] as! TestObjCValueTy
+ expectEqual(1010, v.value)
+ }
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.ArrayIsCopied") {
+ var (a, nsa) = getBridgedNonverbatimArrayAndNSMutableArray()
+ expectTrue(isNativeArray(a))
+
+ // Find an existing value.
+ do {
+ let v = a[0]
+ expectEqual(1010, v.value)
+ }
+
+ // Remove the value from the NSMutableArray.
+ nsa.removeObject(at: 0)
+
+ // Find an existing value, again.
+ do {
+ let v = a[0]
+ expectEqual(1010, v.value)
+ }
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.NSArrayIsRetained") {
+ let nsa: NSArray = autoreleasepool {
+ NSArray(array: getAsNSArray([1010, 1020, 1030]))
+ }
+
+ let a: [AnyObject] = convertNSArrayToArray(nsa)
+
+ let bridgedBack: NSArray = convertArrayToNSArray(a)
+
+ expectEqual(
+ unsafeBitCast(nsa, to: Int.self),
+ unsafeBitCast(bridgedBack, to: Int.self))
+
+ _blackHole(nsa)
+ _blackHole(a)
+ _blackHole(bridgedBack)
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.NSArrayIsCopied") {
+ let nsa: NSArray = autoreleasepool {
+ NSArray(array: getAsNSArray([1010, 1020, 1030]))
+ }
+
+ let a: [TestBridgedValueTy] = convertNSArrayToArray(nsa)
+
+ let bridgedBack: NSArray = convertArrayToNSArray(a)
+
+ expectNotEqual(
+ unsafeBitCast(nsa, to: Int.self),
+ unsafeBitCast(bridgedBack, to: Int.self))
+
+ _blackHole(nsa)
+ _blackHole(a)
+ _blackHole(bridgedBack)
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.ImmutableArrayIsRetained") {
+ let nsa: NSArray = CustomImmutableNSArray(_privateInit: ())
+
+ CustomImmutableNSArray.timesCopyWithZoneWasCalled = 0
+ CustomImmutableNSArray.timesObjectAtIndexWasCalled = 0
+ CustomImmutableNSArray.timesObjectEnumeratorWasCalled = 0
+ CustomImmutableNSArray.timesCountWasCalled = 0
+ let a: [AnyObject] = convertNSArrayToArray(nsa)
+ expectEqual(1, CustomImmutableNSArray.timesCopyWithZoneWasCalled)
+ expectEqual(0, CustomImmutableNSArray.timesObjectAtIndexWasCalled)
+ expectEqual(0, CustomImmutableNSArray.timesObjectEnumeratorWasCalled)
+ expectEqual(0, CustomImmutableNSArray.timesCountWasCalled)
+
+ let bridgedBack: NSArray = convertArrayToNSArray(a)
+ expectEqual(
+ unsafeBitCast(nsa, to: Int.self),
+ unsafeBitCast(bridgedBack, to: Int.self))
+
+ _blackHole(nsa)
+ _blackHole(a)
+ _blackHole(bridgedBack)
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.ImmutableArrayIsCopied") {
+ let nsa: NSArray = CustomImmutableNSArray(_privateInit: ())
+
+ CustomImmutableNSArray.timesCopyWithZoneWasCalled = 0
+ CustomImmutableNSArray.timesObjectAtIndexWasCalled = 0
+ CustomImmutableNSArray.timesObjectEnumeratorWasCalled = 0
+ CustomImmutableNSArray.timesCountWasCalled = 0
+ TestBridgedValueTy.bridgeOperations = 0
+ let a: [TestBridgedValueTy] = convertNSArrayToArray(nsa)
+ //FIXME: Why is this copied?
+ expectEqual(1, CustomImmutableNSArray.timesCopyWithZoneWasCalled)
+ expectEqual(3, CustomImmutableNSArray.timesObjectAtIndexWasCalled)
+ expectNotEqual(0, CustomImmutableNSArray.timesCountWasCalled)
+ expectEqual(3, TestBridgedValueTy.bridgeOperations)
+
+ let bridgedBack: NSArray = convertArrayToNSArray(a)
+ expectNotEqual(
+ unsafeBitCast(nsa, to: Int.self),
+ unsafeBitCast(bridgedBack, to: Int.self))
+
+ _blackHole(nsa)
+ _blackHole(a)
+ _blackHole(bridgedBack)
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.Subscript") {
+ let a = getBridgedVerbatimArray()
+ let identity1 = a._rawIdentifier()
+ expectTrue(isCocoaArray(a))
+
+ // Find an existing value.
+ do {
+ var v = a[0]
+ expectEqual(1010, (v as! TestObjCValueTy).value)
+
+ v = a[1]
+ expectEqual(1020, (v as! TestObjCValueTy).value)
+
+ v = a[2]
+ expectEqual(1030, (v as! TestObjCValueTy).value)
+ }
+ expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.Subscript") {
+ var a = getBridgedNonverbatimArray()
+ let identity1 = a._rawIdentifier()
+ expectTrue(isNativeArray(a))
+
+ // Find an existing value.
+ do {
+ var v = a[0]
+ expectEqual(1010, v.value)
+
+ v = a[1]
+ expectEqual(1020, v.value)
+
+ v = a[2]
+ expectEqual(1030, v.value)
+ }
+ expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.RemoveAt") {
+ var a = getBridgedVerbatimArray()
+ let identity = a._rawIdentifier()
+ expectTrue(isCocoaArray(a))
+
+ let index = 0
+ expectEqual(1010, (a[index] as! TestObjCValueTy).value)
+ expectEqual(identity, a._rawIdentifier())
+
+ let removedElement = a.remove(at: index)
+ expectNotEqual(identity, a._rawIdentifier())
+ expectTrue(isNativeArray(a))
+ expectEqual(1010, (removedElement as! TestObjCValueTy).value)
+ expectEqual(2, a.count)
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.RemoveAt") {
+ var a = getBridgedNonverbatimArray()
+ let identity = a._rawIdentifier()
+ expectTrue(isNativeArray(a))
+
+ let index = 0
+ expectEqual(1010, a[index].value)
+ expectEqual(identity, a._rawIdentifier())
+
+ let removedElement = a.remove(at: index)
+ expectEqual(identity, a._rawIdentifier())
+ expectTrue(isNativeArray(a))
+ expectEqual(1010, removedElement.value)
+ expectEqual(2, a.count)
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.RemoveAll") {
+ do {
+ var a = getBridgedVerbatimArray()
+ let identity1 = a._rawIdentifier()
+ expectTrue(isCocoaArray(a))
+ let originalCapacity = a.count
+ expectEqual(3, a.count)
+ expectEqual(1010, (a[0] as! TestObjCValueTy).value)
+
+ a.removeAll()
+ expectNotEqual(identity1, a._rawIdentifier())
+ expectLT(a._buffer.capacity, originalCapacity)
+ expectEqual(0, a.count)
+ }
+
+ do {
+ var a = getBridgedVerbatimArray()
+ let identity1 = a._rawIdentifier()
+ expectTrue(isCocoaArray(a))
+ let originalCapacity = a.count
+ expectEqual(3, a.count)
+ expectEqual(1010, (a[0] as! TestObjCValueTy).value)
+
+ a.removeAll(keepingCapacity: true)
+ expectNotEqual(identity1, a._rawIdentifier())
+ expectGE(a._buffer.capacity, originalCapacity)
+ expectEqual(0, a.count)
+ }
+
+ do {
+ var a1 = getBridgedVerbatimArray()
+ let identity1 = a1._rawIdentifier()
+ expectTrue(isCocoaArray(a1))
+ let originalCapacity = a1.count
+ expectEqual(3, a1.count)
+ expectEqual(1010, (a1[0] as! TestObjCValueTy).value)
+
+ var a2 = a1
+ a2.removeAll()
+ let identity2 = a2._rawIdentifier()
+ expectEqual(identity1, a1._rawIdentifier())
+ expectNotEqual(identity2, identity1)
+ expectEqual(3, a1.count)
+ expectEqual(1010, (a1[0] as! TestObjCValueTy).value)
+ expectLT(a2._buffer.capacity, originalCapacity)
+ expectEqual(0, a2.count)
+ }
+
+ do {
+ var a1 = getBridgedVerbatimArray()
+ let identity1 = a1._rawIdentifier()
+ expectTrue(isCocoaArray(a1))
+ let originalCapacity = a1.count
+ expectEqual(3, a1.count)
+ expectEqual(1010, (a1[0] as! TestObjCValueTy).value)
+
+ var a2 = a1
+ a2.removeAll(keepingCapacity: true)
+ let identity2 = a2._rawIdentifier()
+ expectEqual(identity1, a1._rawIdentifier())
+ expectNotEqual(identity2, identity1)
+ expectEqual(3, a1.count)
+ expectEqual(1010, (a1[0] as! TestObjCValueTy).value)
+ expectGE(a2._buffer.capacity, originalCapacity)
+ expectEqual(0, a2.count)
+ }
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.RemoveAll") {
+ do {
+ var a = getBridgedNonverbatimArray()
+ let identity1 = a._rawIdentifier()
+ expectTrue(isNativeArray(a))
+ let originalCapacity = a.count
+ expectEqual(3, a.count)
+ expectEqual(1010, a[0].value)
+
+ a.removeAll()
+ expectNotEqual(identity1, a._rawIdentifier())
+ expectLT(a._buffer.capacity, originalCapacity)
+ expectEqual(0, a.count)
+ }
+
+ do {
+ var a = getBridgedNonverbatimArray()
+ let identity1 = a._rawIdentifier()
+ expectTrue(isNativeArray(a))
+ let originalCapacity = a.count
+ expectEqual(3, a.count)
+ expectEqual(1010, a[0].value)
+
+ a.removeAll(keepingCapacity: true)
+ expectEqual(identity1, a._rawIdentifier())
+ expectGE(a._buffer.capacity, originalCapacity)
+ expectEqual(0, a.count)
+ }
+
+ do {
+ var a1 = getBridgedNonverbatimArray()
+ let identity1 = a1._rawIdentifier()
+ expectTrue(isNativeArray(a1))
+ let originalCapacity = a1.count
+ expectEqual(3, a1.count)
+ expectEqual(1010, a1[0].value)
+
+ var a2 = a1
+ a2.removeAll()
+ let identity2 = a2._rawIdentifier()
+ expectEqual(identity1, a1._rawIdentifier())
+ expectNotEqual(identity2, identity1)
+ expectEqual(3, a1.count)
+ expectEqual(1010, a1[0].value)
+ expectLT(a2._buffer.capacity, originalCapacity)
+ expectEqual(0, a2.count)
+ }
+
+ do {
+ var a1 = getBridgedNonverbatimArray()
+ let identity1 = a1._rawIdentifier()
+ expectTrue(isNativeArray(a1))
+ let originalCapacity = a1.count
+ expectEqual(3, a1.count)
+ expectEqual(1010, a1[0].value)
+
+ var a2 = a1
+ a2.removeAll(keepingCapacity: true)
+ let identity2 = a2._rawIdentifier()
+ expectEqual(identity1, a1._rawIdentifier())
+ expectNotEqual(identity2, identity1)
+ expectEqual(3, a1.count)
+ expectEqual(1010, a1[0].value)
+ expectGE(a2._buffer.capacity, originalCapacity)
+ expectEqual(0, a2.count)
+ }
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.Count") {
+ let a = getBridgedVerbatimArray()
+ let identity1 = a._rawIdentifier()
+ expectTrue(isCocoaArray(a))
+
+ expectEqual(3, a.count)
+ expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.Count") {
+ let a = getBridgedNonverbatimArray()
+ let identity1 = a._rawIdentifier()
+ expectTrue(isNativeArray(a))
+
+ expectEqual(3, a.count)
+ expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.Generate") {
+ let a = getBridgedVerbatimArray()
+ let identity1 = a._rawIdentifier()
+ expectTrue(isCocoaArray(a))
+
+ var iter = a.makeIterator()
+ var values = Array<Int>()
+ while let value = iter.next() {
+ values.append((value as! TestObjCValueTy).value)
+ }
+ expectEqual(values, [1010, 1020, 1030])
+ expectNil(iter.next())
+ expectNil(iter.next())
+ expectNil(iter.next())
+ expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.Generate") {
+ let a = getBridgedNonverbatimArray()
+ let identity1 = a._rawIdentifier()
+ expectTrue(isNativeArray(a))
+
+ var iter = a.makeIterator()
+ var values = Array<Int>()
+ while let value = iter.next() {
+ values.append(value.value)
+ }
+ expectEqual(values, [1010, 1020, 1030])
+ expectNil(iter.next())
+ expectNil(iter.next())
+ expectNil(iter.next())
+ expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.Generate_Empty") {
+ let a = getBridgedVerbatimArray([])
+ let identity1 = a._rawIdentifier()
+ expectTrue(isCocoaArray(a))
+
+ var iter = a.makeIterator()
+ expectNil(iter.next())
+ expectNil(iter.next())
+ expectNil(iter.next())
+ expectNil(iter.next())
+ expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.Generate_Empty") {
+ let a = getBridgedNonverbatimArray([])
+ let identity1 = a._rawIdentifier()
+ expectTrue(isNativeArray(a))
+
+ var iter = a.makeIterator()
+ expectNil(iter.next())
+ expectNil(iter.next())
+ expectNil(iter.next())
+ expectNil(iter.next())
+ expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.Generate_Huge") {
+ let a = getHugeBridgedVerbatimArray()
+ let identity1 = a._rawIdentifier()
+ expectTrue(isCocoaArray(a))
+
+ var iter = a.makeIterator()
+ var values = Array<Int>()
+ while let value = iter.next() {
+ values.append((value as! TestObjCValueTy).value)
+ }
+ var expectedValues = Array<Int>()
+ for i in 1...32 {
+ expectedValues += [1000 + i]
+ }
+ expectEqual(values, expectedValues)
+ expectNil(iter.next())
+ expectNil(iter.next())
+ expectNil(iter.next())
+ expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.Generate_Huge") {
+ let a = getHugeBridgedNonverbatimArray()
+ let identity1 = a._rawIdentifier()
+ expectTrue(isNativeArray(a))
+
+ var iter = a.makeIterator()
+ var values = Array<Int>()
+ while let value = iter.next() {
+ values.append(value.value)
+ }
+ var expectedValues = Array<Int>()
+ for i in 1...32 {
+ expectedValues += [1000 + i]
+ }
+ expectEqual(values, expectedValues)
+ expectNil(iter.next())
+ expectNil(iter.next())
+ expectNil(iter.next())
+ expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.EqualityTest_Empty") {
+ let a1 = getBridgedVerbatimEquatableArray([])
+ let identity1 = a1._rawIdentifier()
+ expectTrue(isCocoaArray(a1))
+
+ let a2 = getBridgedVerbatimEquatableArray([])
+ let identity2 = a2._rawIdentifier()
+ expectTrue(isCocoaArray(a2))
+
+ // We can't check that `identity1 != identity2` because Foundation might be
+ // returning the same singleton NSArray for empty arrays.
+
+ expectEqual(a1, a2)
+ expectEqual(identity1, a1._rawIdentifier())
+ expectEqual(identity2, a2._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.EqualityTest_Empty") {
+ var a1 = getBridgedNonverbatimEquatableArray([])
+ a1.append(TestBridgedEquatableValueTy(1))
+ a1.removeLast()
+ let identity1 = a1._rawIdentifier()
+ expectTrue(isNativeArray(a1))
+
+ let a2 = getBridgedNonverbatimEquatableArray([])
+ let identity2 = a2._rawIdentifier()
+ expectTrue(isNativeArray(a2))
+ expectNotEqual(identity1, identity2)
+
+ expectEqual(a1, a2)
+ expectEqual(identity1, a1._rawIdentifier())
+ expectEqual(identity2, a2._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.EqualityTest_Small") {
+ func helper(_ na1: Array<Int>, _ na2: Array<Int>, _ expectedEq: Bool) {
+ let a1 = getBridgedVerbatimEquatableArray(na1)
+ let identity1 = a1._rawIdentifier()
+ expectTrue(isCocoaArray(a1))
+
+ var a2 = getBridgedVerbatimEquatableArray(na2)
+ var identity2 = a2._rawIdentifier()
+ expectTrue(isCocoaArray(a2))
+
+ do {
+ let eq1 = (a1 == a2)
+ expectEqual(eq1, expectedEq)
+
+ let eq2 = (a2 == a1)
+ expectEqual(eq2, expectedEq)
+
+ let neq1 = (a1 != a2)
+ expectNotEqual(neq1, expectedEq)
+
+ let neq2 = (a2 != a1)
+ expectNotEqual(neq2, expectedEq)
+ }
+ expectEqual(identity1, a1._rawIdentifier())
+ expectEqual(identity2, a2._rawIdentifier())
+
+ a2.append(TestObjCEquatableValueTy(1111))
+ a2.removeLast()
+ expectTrue(isNativeArray(a2))
+ expectNotEqual(identity2, a2._rawIdentifier())
+ identity2 = a2._rawIdentifier()
+
+ do {
+ let eq1 = (a1 == a2)
+ expectEqual(eq1, expectedEq)
+
+ let eq2 = (a2 == a1)
+ expectEqual(eq2, expectedEq)
+
+ let neq1 = (a1 != a2)
+ expectNotEqual(neq1, expectedEq)
+
+ let neq2 = (a2 != a1)
+ expectNotEqual(neq2, expectedEq)
+ }
+ expectEqual(identity1, a1._rawIdentifier())
+ expectEqual(identity2, a2._rawIdentifier())
+ }
+
+ helper([], [], true)
+
+ helper([1010],
+ [1010],
+ true)
+
+ helper([1010, 1020],
+ [1010, 1020],
+ true)
+
+ helper([1010, 1020, 1030],
+ [1010, 1020, 1030],
+ true)
+
+ helper([1010, 1020, 1030],
+ [1010, 1020, 1111],
+ false)
+
+ helper([1010, 1020, 1030],
+ [1010, 1020],
+ false)
+
+ helper([1010, 1020, 1030],
+ [1010],
+ false)
+
+ helper([1010, 1020, 1030],
+ [],
+ false)
+
+ helper([1010, 1020, 1030],
+ [1010, 1020, 1030, 1040],
+ false)
+}
+
+//===---
+// Array -> NSArray bridging tests.
+//
+// Values are bridged verbatim.
+//===---
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.Count") {
+ let d = getBridgedNSArrayOfRefTypesBridgedVerbatim()
+
+ expectEqual(3, d.count)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.ObjectForKey") {
+ let a = getBridgedNSArrayOfRefTypesBridgedVerbatim()
+
+ var v: AnyObject? = a.object(at: 0) as AnyObject
+ expectEqual(1010, (v as! TestObjCValueTy).value)
+ let idValue10 = unsafeBitCast(v, to: UInt.self)
+
+ v = a.object(at: 1) as AnyObject
+ expectEqual(1020, (v as! TestObjCValueTy).value)
+ let idValue20 = unsafeBitCast(v, to: UInt.self)
+
+ v = a.object(at: 2) as AnyObject
+ expectEqual(1030, (v as! TestObjCValueTy).value)
+ let idValue30 = unsafeBitCast(v, to: UInt.self)
+
+ for _ in 0..<3 {
+ expectEqual(idValue10, unsafeBitCast(
+ a.object(at: 0) as AnyObject, to: UInt.self))
+
+ expectEqual(idValue20, unsafeBitCast(
+ a.object(at: 1) as AnyObject, to: UInt.self))
+
+ expectEqual(idValue30, unsafeBitCast(
+ a.object(at: 2) as AnyObject, to: UInt.self))
+ }
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.KeyEnumerator.NextObject") {
+ let a = getBridgedNSArrayOfRefTypesBridgedVerbatim()
+
+ var capturedIdentities = Array<UInt>()
+
+ for _ in 0..<3 {
+ let enumerator = a.objectEnumerator()
+
+ var values = Array<Int>()
+ var identities = Array<UInt>()
+ while let value = enumerator.nextObject() {
+ let valueObj = (value as! TestObjCValueTy)
+ values.append(valueObj.value)
+
+ let identity = unsafeBitCast(valueObj, to: UInt.self)
+ identities.append(identity)
+ }
+ expectEqual([ 1010, 1020, 1030 ], values)
+
+ if capturedIdentities.isEmpty {
+ capturedIdentities = identities
+ } else {
+ expectEqual(capturedIdentities, identities)
+ }
+
+ expectNil(enumerator.nextObject())
+ expectNil(enumerator.nextObject())
+ expectNil(enumerator.nextObject())
+ }
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.ObjectEnumerator.NextObject_Empty") {
+ let a = getBridgedEmptyNSArray()
+ let enumerator = a.objectEnumerator()
+
+ expectNil(enumerator.nextObject())
+ expectNil(enumerator.nextObject())
+ expectNil(enumerator.nextObject())
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.ObjectEnumerator.FastEnumeration.UseFromSwift") {
+ let a = getBridgedNSArrayOfRefTypesBridgedVerbatim()
+
+ checkArrayFastEnumerationFromSwift(
+ [ 1010, 1020, 1030 ],
+ a, { a.objectEnumerator() },
+ { ($0 as! TestObjCValueTy).value })
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.ObjectEnumerator.FastEnumeration.UseFromObjC") {
+ let a = getBridgedNSArrayOfRefTypesBridgedVerbatim()
+
+ checkArrayFastEnumerationFromObjC(
+ [ 1010, 1020, 1030 ],
+ a, { a.objectEnumerator() },
+ { ($0 as! TestObjCValueTy).value })
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.ObjectEnumerator.FastEnumeration_Empty") {
+ let a = getBridgedEmptyNSArray()
+
+ checkArrayFastEnumerationFromSwift(
+ [], a, { a.objectEnumerator() },
+ { ($0 as! TestObjCValueTy).value })
+
+ checkArrayFastEnumerationFromObjC(
+ [], a, { a.objectEnumerator() },
+ { ($0 as! TestObjCValueTy).value })
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.FastEnumeration.UseFromSwift") {
+ let a = getBridgedNSArrayOfRefTypesBridgedVerbatim()
+
+ checkArrayFastEnumerationFromSwift(
+ [ 1010, 1020, 1030 ],
+ a, { a },
+ { ($0 as! TestObjCValueTy).value })
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.FastEnumeration.UseFromObjC") {
+ let a = getBridgedNSArrayOfRefTypesBridgedVerbatim()
+
+ checkArrayFastEnumerationFromObjC(
+ [ 1010, 1020, 1030 ],
+ a, { a },
+ { ($0 as! TestObjCValueTy).value })
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.FastEnumeration_Empty") {
+ let a = getBridgedEmptyNSArray()
+
+ checkArrayFastEnumerationFromSwift(
+ [], a, { a },
+ { ($0 as! TestObjCValueTy).value })
+
+ checkArrayFastEnumerationFromObjC(
+ [], a, { a },
+ { ($0 as! TestObjCValueTy).value })
+}
+
+//===---
+// Array -> NSArray bridging tests.
+//
+// Values are bridged non-verbatim.
+//===---
+
+ArrayTestSuite.test("BridgedToObjC.KeyValue_ValueTypesCustomBridged") {
+ let a = getBridgedNSArrayOfObjValue_ValueTypesCustomBridged()
+ let enumerator = a.objectEnumerator()
+
+ var values = Array<Int>()
+ while let valueObj = enumerator.nextObject() {
+ let value: AnyObject = valueObj as AnyObject
+ let v = (value as! TestObjCValueTy).value
+ values.append(v)
+ }
+ expectEqual([ 1010, 1020, 1030 ], values)
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Custom.ObjectEnumerator.FastEnumeration.UseFromSwift") {
+ let a = getBridgedNSArrayOfObjValue_ValueTypesCustomBridged()
+
+ checkArrayFastEnumerationFromSwift(
+ [ 1010, 1020, 1030 ],
+ a, { a.objectEnumerator() },
+ { ($0 as! TestObjCValueTy).value })
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Custom.ObjectEnumerator.FastEnumeration.UseFromSwift.Partial") {
+ let a = getBridgedNSArrayOfObjValue_ValueTypesCustomBridged(
+ numElements: 9)
+
+ checkArrayEnumeratorPartialFastEnumerationFromSwift(
+ [ 1010, 1020, 1030, 1040, 1050,
+ 1060, 1070, 1080, 1090 ],
+ a, maxFastEnumerationItems: 5,
+ { ($0 as! TestObjCValueTy).value })
+
+ expectAutoreleasedValues(unopt: 9)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Custom.ObjectEnumerator.FastEnumeration.UseFromObjC") {
+ let a = getBridgedNSArrayOfObjValue_ValueTypesCustomBridged()
+
+ checkArrayFastEnumerationFromObjC(
+ [ 1010, 1020, 1030 ],
+ a, { a.objectEnumerator() },
+ { ($0 as! TestObjCValueTy).value })
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Custom.FastEnumeration.UseFromSwift") {
+ let a = getBridgedNSArrayOfObjValue_ValueTypesCustomBridged()
+
+ checkArrayFastEnumerationFromSwift(
+ [ 1010, 1020, 1030 ],
+ a, { a },
+ { ($0 as! TestObjCValueTy).value })
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Custom.FastEnumeration.UseFromObjC") {
+ let a = getBridgedNSArrayOfObjValue_ValueTypesCustomBridged()
+
+ checkArrayFastEnumerationFromObjC(
+ [ 1010, 1020, 1030 ],
+ a, { a },
+ { ($0 as! TestObjCValueTy).value })
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Custom.FastEnumeration_Empty") {
+ let a = getBridgedNSArrayOfObjValue_ValueTypesCustomBridged(
+ numElements: 0)
+
+ checkArrayFastEnumerationFromSwift(
+ [], a, { a },
+ { ($0 as! TestObjCValueTy).value })
+
+ checkArrayFastEnumerationFromObjC(
+ [], a, { a },
+ { ($0 as! TestObjCValueTy).value })
+}
+
+ArrayTestSuite.test("BridgedToObjC.Key_ValueTypeCustomBridged") {
+ let a = getBridgedNSArrayOfObj_ValueTypeCustomBridged()
+ let enumerator = a.objectEnumerator()
+
+ var values = Array<Int>()
+ while let valueObj = enumerator.nextObject() {
+ let value: AnyObject = valueObj as AnyObject
+ let v = (value as! TestObjCValueTy).value
+ values.append(v)
+ }
+ expectEqual([ 1010, 1020, 1030 ], values)
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Value_ValueTypeCustomBridged") {
+ let a = getBridgedNSArrayOfValue_ValueTypeCustomBridged()
+ let enumerator = a.objectEnumerator()
+
+ var values = Array<Int>()
+ while let valueObj = enumerator.nextObject() {
+ let value: AnyObject = valueObj as AnyObject
+ let v = (value as! TestObjCValueTy).value
+ values.append(v)
+ }
+ expectEqual([ 1010, 1020, 1030 ], values)
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+//===---
+// NSArray -> Array -> NSArray bridging tests.
+//===---
+
+ArrayTestSuite.test("BridgingRoundtrip") {
+ let a = getRoundtripBridgedNSArray()
+ let enumerator = a.objectEnumerator()
+
+ var values = Array<Int>()
+ while let valueObj = enumerator.nextObject() {
+ let value: AnyObject = valueObj as AnyObject
+ let v = (value as! TestObjCValueTy).value
+ values.append(v)
+ }
+ expectEqual([ 1010, 1020, 1030 ], values)
+}
+
+//===---
+// NSArray -> Array implicit conversion.
+//===---
+
+ArrayTestSuite.test("NSArrayToArrayConversion") {
+ let values = [ 1010, 1020, 1030 ].map { TestObjCValueTy($0) }
+
+ let nsa = NSArray(array: values)
+
+ let a: Array = nsa as Array
+
+ var bridgedValues = Array<Int>()
+ for value in a {
+ let v = (value as! TestObjCValueTy).value
+ bridgedValues.append(v)
+ }
+ expectEqual([ 1010, 1020, 1030 ], bridgedValues)
+}
+
+ArrayTestSuite.test("ArrayToNSArrayConversion") {
+ var a = Array<TestObjCValueTy>()
+ a.append(TestObjCValueTy(1010))
+ a.append(TestObjCValueTy(1020))
+ a.append(TestObjCValueTy(1030))
+ let nsa: NSArray = a as NSArray
+
+ checkArrayFastEnumerationFromSwift(
+ [ 1010, 1020, 1030 ],
+ nsa, { a as NSArray },
+ { ($0 as! TestObjCValueTy).value })
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+//===---
+// Array upcasts
+//===---
+
+ArrayTestSuite.test("ArrayUpcastEntryPoint") {
+ var a = Array<TestObjCValueTy>()
+ a.append(TestObjCValueTy(1010))
+ a.append(TestObjCValueTy(1020))
+ a.append(TestObjCValueTy(1030))
+
+ var aAsAnyObject: Array<AnyObject> = _arrayForceCast(a)
+
+ expectEqual(3, aAsAnyObject.count)
+ var v: AnyObject = aAsAnyObject[0]
+ expectEqual(1010, (v as! TestObjCValueTy).value)
+
+ v = aAsAnyObject[1]
+ expectEqual(1020, (v as! TestObjCValueTy).value)
+
+ v = aAsAnyObject[2]
+ expectEqual(1030, (v as! TestObjCValueTy).value)
+}
+
+ArrayTestSuite.test("ArrayUpcast") {
+ var a = Array<TestObjCValueTy>()
+ a.append(TestObjCValueTy(1010))
+ a.append(TestObjCValueTy(1020))
+ a.append(TestObjCValueTy(1030))
+
+ var dAsAnyObject: Array<AnyObject> = a
+
+ expectEqual(3, dAsAnyObject.count)
+ var v: AnyObject = dAsAnyObject[0]
+ expectEqual(1010, (v as! TestObjCValueTy).value)
+
+ v = dAsAnyObject[1]
+ expectEqual(1020, (v as! TestObjCValueTy).value)
+
+ v = dAsAnyObject[2]
+ expectEqual(1030, (v as! TestObjCValueTy).value)
+}
+
+ArrayTestSuite.test("ArrayUpcastBridgedEntryPoint") {
+ var a = Array<TestBridgedValueTy>()
+ a.append(TestBridgedValueTy(1010))
+ a.append(TestBridgedValueTy(1020))
+ a.append(TestBridgedValueTy(1030))
+
+ do {
+ var aOO: Array<AnyObject> = _arrayConditionalCast(a)!
+
+ expectEqual(3, aOO.count)
+ var v: AnyObject = aOO[0]
+ expectEqual(1010, (v as! TestBridgedValueTy).value)
+
+ v = aOO[1]
+ expectEqual(1020, (v as! TestBridgedValueTy).value)
+
+ v = aOO[2]
+ expectEqual(1030, (v as! TestBridgedValueTy).value)
+ }
+}
+
+ArrayTestSuite.test("ArrayUpcastBridged") {
+ var a = Array<TestBridgedValueTy>()
+ a.append(TestBridgedValueTy(1010))
+ a.append(TestBridgedValueTy(1020))
+ a.append(TestBridgedValueTy(1030))
+
+ do {
+ var aOO = a as Array<AnyObject>
+
+ expectEqual(3, aOO.count)
+ var v: AnyObject = aOO[0]
+ expectEqual(1010, (v as! TestBridgedValueTy).value)
+
+ v = aOO[1]
+ expectEqual(1020, (v as! TestBridgedValueTy).value)
+
+ v = aOO[2]
+ expectEqual(1030, (v as! TestBridgedValueTy).value)
+ }
+}
+
+//===---
+// Array downcasts
+//===---
+
+ArrayTestSuite.test("ArrayDowncastEntryPoint") {
+ var a = Array<AnyObject>()
+ a.append(TestObjCValueTy(1010))
+ a.append(TestObjCValueTy(1020))
+ a.append(TestObjCValueTy(1030))
+
+ // Successful downcast.
+ let aCC: Array<TestObjCValueTy> = _arrayForceCast(a)
+ expectEqual(3, aCC.count)
+ var v = aCC[0]
+ expectEqual(1010, v.value)
+
+ v = aCC[1]
+ expectEqual(1020, v.value)
+
+ v = aCC[2]
+ expectEqual(1030, v.value)
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("ArrayDowncast") {
+ var a = Array<AnyObject>()
+ a.append(TestObjCValueTy(1010))
+ a.append(TestObjCValueTy(1020))
+ a.append(TestObjCValueTy(1030))
+
+ // Successful downcast.
+ let aCC = a as! Array<TestObjCValueTy>
+ expectEqual(3, aCC.count)
+ var v = aCC[0]
+ expectEqual(1010, v.value)
+
+ v = aCC[1]
+ expectEqual(1020, v.value)
+
+ v = aCC[2]
+ expectEqual(1030, v.value)
+
+ expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("ArrayDowncastConditionalEntryPoint") {
+ var a = Array<AnyObject>()
+ a.append(TestObjCValueTy(1010))
+ a.append(TestObjCValueTy(1020))
+ a.append(TestObjCValueTy(1030))
+
+ // Successful downcast.
+ if let aCC
+ = _arrayConditionalCast(a) as Array<TestObjCValueTy>? {
+ expectEqual(3, aCC.count)
+ var v = aCC[0]
+ expectEqual(1010, v.value)
+
+ v = aCC[1]
+ expectEqual(1020, v.value)
+
+ v = aCC[2]
+ expectEqual(1030, v.value)
+ } else {
+ expectTrue(false)
+ }
+
+ // Unsuccessful downcast
+ a[0] = 17 as NSNumber
+ a[1] = "hello" as NSString
+ if let _ = _arrayConditionalCast(a) as Array<TestObjCValueTy>? {
+ expectTrue(false)
+ }
+}
+
+ArrayTestSuite.test("ArrayDowncastConditional") {
+ var a = Array<AnyObject>()
+ a.append(TestObjCValueTy(1010))
+ a.append(TestObjCValueTy(1020))
+ a.append(TestObjCValueTy(1030))
+
+ // Successful downcast.
+ if let aCC = a as? Array<TestObjCValueTy> {
+ expectEqual(3, aCC.count)
+ var v = aCC[0]
+ expectEqual(1010, v.value)
+
+ v = aCC[1]
+ expectEqual(1020, v.value)
+
+ v = aCC[2]
+ expectEqual(1030, v.value)
+ } else {
+ expectTrue(false)
+ }
+
+ // Unsuccessful downcast
+ a[0] = 17 as NSNumber
+ a[1] = "hello" as NSString
+ if let _ = a as? Array<TestObjCValueTy> {
+ expectTrue(false)
+ }
+}
+
+ArrayTestSuite.test("ArrayBridgeFromObjectiveCEntryPoint") {
+ var a = Array<AnyObject>()
+ a.append(TestObjCValueTy(1010))
+ a.append(TestObjCValueTy(1020))
+ a.append(TestObjCValueTy(1030))
+
+ // Successful downcast.
+ let aCV: Array<TestBridgedValueTy> = _arrayConditionalCast(a)!
+ do {
+ expectEqual(3, aCV.count)
+ var v = aCV[0]
+ expectEqual(1010, v.value)
+
+ v = aCV[1]
+ expectEqual(1020, v.value)
+
+ v = aCV[2]
+ expectEqual(1030, v.value)
+ }
+
+ // // Successful downcast.
+ let aVC: Array<TestObjCValueTy> = _arrayConditionalCast(a)!
+ do {
+ expectEqual(3, aVC.count)
+ var v = aVC[0]
+ expectEqual(1010, v.value)
+
+ v = aVC[1]
+ expectEqual(1020, v.value)
+
+ v = aVC[2]
+ expectEqual(1030, v.value)
+ }
+}
+
+ArrayTestSuite.test("ArrayBridgeFromObjectiveC") {
+ var a = Array<AnyObject>()
+ a.append(TestObjCValueTy(1010))
+ a.append(TestObjCValueTy(1020))
+ a.append(TestObjCValueTy(1030))
+
+ // Successful downcast.
+ let aCV = a as! Array<TestBridgedValueTy>
+ do {
+ expectEqual(3, aCV.count)
+ var v = aCV[0]
+ expectEqual(1010, v.value)
+
+ v = aCV[1]
+ expectEqual(1020, v.value)
+
+ v = aCV[2]
+ expectEqual(1030, v.value)
+ }
+
+ // Successful downcast.
+ let aVC = a as! Array<TestObjCValueTy>
+ do {
+ expectEqual(3, aVC.count)
+ var v = aVC[0]
+ expectEqual(1010, v.value)
+
+ v = aVC[1]
+ expectEqual(1020, v.value)
+
+ v = aVC[2]
+ expectEqual(1030, v.value)
+ }
+}
+
+ArrayTestSuite.test("ArrayBridgeFromObjectiveCConditionalEntryPoint") {
+ var a = Array<AnyObject>()
+ a.append(TestObjCValueTy(1010))
+ a.append(TestObjCValueTy(1020))
+ a.append(TestObjCValueTy(1030))
+
+ // Successful downcast.
+ if let aCV = _arrayConditionalCast(a) as Array<TestBridgedValueTy>? {
+ expectEqual(3, aCV.count)
+ var v = aCV[0]
+ expectEqual(1010, v.value)
+
+ v = aCV[1]
+ expectEqual(1020, v.value)
+
+ v = aCV[2]
+ expectEqual(1030, v.value)
+ } else {
+ expectTrue(false)
+ }
+
+ // Successful downcast.
+ if let aVC = _arrayConditionalCast(a) as Array<TestObjCValueTy>? {
+ expectEqual(3, aVC.count)
+ var v = aVC[0]
+ expectEqual(1010, v.value)
+
+ v = aVC[1]
+ expectEqual(1020, v.value)
+
+ v = aVC[2]
+ expectEqual(1030, v.value)
+ } else {
+ expectTrue(false)
+ }
+
+ // Unsuccessful downcasts
+ a[0] = 17 as NSNumber
+ a[1] = "hello" as NSString
+ if let _ = _arrayConditionalCast(a) as Array<TestBridgedValueTy>? {
+ expectTrue(false)
+ }
+ if let _ = _arrayConditionalCast(a) as Array<TestObjCValueTy>? {
+ expectTrue(false)
+ }
+}
+
+ArrayTestSuite.test("ArrayBridgeFromObjectiveCConditional") {
+ var a = Array<AnyObject>()
+ a.append(TestObjCValueTy(1010))
+ a.append(TestObjCValueTy(1020))
+ a.append(TestObjCValueTy(1030))
+
+ // Successful downcast.
+ if let aCV = a as? Array<TestBridgedValueTy> {
+ expectEqual(3, aCV.count)
+ var v = aCV[0]
+ expectEqual(1010, v.value)
+
+ v = aCV[1]
+ expectEqual(1020, v.value)
+
+ v = aCV[2]
+ expectEqual(1030, v.value)
+ } else {
+ expectTrue(false)
+ }
+
+ // Successful downcast.
+ if let aVC = a as? Array<TestObjCValueTy> {
+ expectEqual(3, aVC.count)
+ var v = aVC[0]
+ expectEqual(1010, v.value)
+
+ v = aVC[1]
+ expectEqual(1020, v.value)
+
+ v = aVC[2]
+ expectEqual(1030, v.value)
+ } else {
+ expectTrue(false)
+ }
+
+ // Unsuccessful downcasts
+ a[0] = 17 as NSNumber
+ a[1] = "hello" as NSString
+ if let _ = a as? Array<TestBridgedValueTy> {
+ expectTrue(false)
+ }
+ if let _ = a as? Array<TestObjCValueTy> {
+ expectTrue(false)
+ }
+}
+
+#endif
+
+//===---
+// Check that iterators traverse a snapshot of the collection.
+//===---
+
+ArrayTestSuite.test("mutationDoesNotAffectIterator/subscript/store") {
+ var array = getDerivedAPIsArray()
+ let iter = array.makeIterator()
+ array[0] = 1011
+
+ expectEqual([1010 ,1020, 1030], Array(IteratorSequence(iter)))
+}
+
+ArrayTestSuite.test("mutationDoesNotAffectIterator/removeAt,1") {
+ var array = getDerivedAPIsArray()
+ let iter = array.makeIterator()
+ expectEqual(1010, array.remove(at: 0))
+
+ expectEqual([1010 ,1020, 1030], Array(IteratorSequence(iter)))
+}
+
+ArrayTestSuite.test("mutationDoesNotAffectIterator/removeAt,all") {
+ var array = getDerivedAPIsArray()
+ let iter = array.makeIterator()
+ expectEqual(1010, array.remove(at: 0))
+ expectEqual(1020, array.remove(at: 0))
+ expectEqual(1030, array.remove(at: 0))
+
+ expectEqual([1010 ,1020, 1030], Array(IteratorSequence(iter)))
+}
+
+ArrayTestSuite.test(
+ "mutationDoesNotAffectIterator/removeAll,keepingCapacity=false") {
+ var array = getDerivedAPIsArray()
+ let iter = array.makeIterator()
+ array.removeAll(keepingCapacity: false)
+
+ expectEqual([1010 ,1020, 1030], Array(IteratorSequence(iter)))
+}
+
+ArrayTestSuite.test(
+ "mutationDoesNotAffectIterator/removeAll,keepingCapacity=true") {
+ var array = getDerivedAPIsArray()
+ let iter = array.makeIterator()
+ array.removeAll(keepingCapacity: true)
+
+ expectEqual([1010 ,1020, 1030], Array(IteratorSequence(iter)))
+}
+
//===----------------------------------------------------------------------===//
// Native array tests
// FIXME: incomplete.
@@ -168,7 +1559,7 @@
ArrayTestSuite.test("COW.Smoke") {
var a1 = Array<COWBox<Int>>(repeating: COWBox(0), count: 10)
- var identity1 = a1._rawIdentifier()
+ let identity1 = a1._rawIdentifier()
a1[0] = COWBox(1)
a1[1] = COWBox(2)
@@ -187,28 +1578,10 @@
_blackHole(a2)
}
-func getCOWFastArray() -> Array<Int> {
- var a = Array<Int>()
- a.reserveCapacity(10)
- a.append(1)
- a.append(2)
- a.append(3)
- return a
-}
-
-func getCOWSlowArray() -> Array<COWBox<Int>> {
- var a = Array<COWBox<Int>>()
- a.reserveCapacity(10)
- a.append(COWBox(1))
- a.append(COWBox(2))
- a.append(COWBox(3))
- return a
-}
-
ArrayTestSuite.test("COW.Fast.SubscriptWithIndexDoesNotReallocate") {
var a = getCOWFastArray()
- var identity1 = a._rawIdentifier()
- var startIndex = a.startIndex
+ let identity1 = a._rawIdentifier()
+ let startIndex = a.startIndex
expectNotEqual(0, a[startIndex])
expectEqual(identity1, a._rawIdentifier())
@@ -216,8 +1589,8 @@
ArrayTestSuite.test("COW.Slow.SubscriptWithIndexDoesNotReallocate") {
var a = getCOWSlowArray()
- var identity1 = a._rawIdentifier()
- var startIndex = a.startIndex
+ let identity1 = a._rawIdentifier()
+ let startIndex = a.startIndex
expectNotEqual(0, a[startIndex].value)
expectEqual(identity1, a._rawIdentifier())
@@ -226,7 +1599,7 @@
ArrayTestSuite.test("COW.Fast.RemoveAtDoesNotReallocate") {
do {
var a = getCOWFastArray()
- var identity1 = a._rawIdentifier()
+ let identity1 = a._rawIdentifier()
let index1 = 1
expectEqual(identity1, a._rawIdentifier())
@@ -240,14 +1613,14 @@
}
do {
- var a1 = getCOWFastArray()
- var identity1 = a1._rawIdentifier()
+ let a1 = getCOWFastArray()
+ let identity1 = a1._rawIdentifier()
var a2 = a1
expectEqual(identity1, a1._rawIdentifier())
expectEqual(identity1, a2._rawIdentifier())
- var index1 = 1
+ let index1 = 1
expectEqual(2, a2[index1])
expectEqual(identity1, a1._rawIdentifier())
expectEqual(identity1, a2._rawIdentifier())
@@ -263,7 +1636,7 @@
ArrayTestSuite.test("COW.Slow.RemoveAtDoesNotReallocate") {
do {
var a = getCOWSlowArray()
- var identity1 = a._rawIdentifier()
+ let identity1 = a._rawIdentifier()
let index1 = 1
expectEqual(identity1, a._rawIdentifier())
@@ -277,14 +1650,14 @@
}
do {
- var a1 = getCOWSlowArray()
- var identity1 = a1._rawIdentifier()
+ let a1 = getCOWSlowArray()
+ let identity1 = a1._rawIdentifier()
var a2 = a1
expectEqual(identity1, a1._rawIdentifier())
expectEqual(identity1, a2._rawIdentifier())
- var index1 = 1
+ let index1 = 1
expectEqual(2, a2[index1].value)
expectEqual(identity1, a1._rawIdentifier())
expectEqual(identity1, a2._rawIdentifier())
@@ -306,7 +1679,7 @@
expectEqual(2, a[1])
a.removeAll()
- var identity1 = a._rawIdentifier()
+ let identity1 = a._rawIdentifier()
expectLT(a.capacity, originalCapacity)
expectEqual(0, a.count)
expectEqual(identity1, a._rawIdentifier())
@@ -314,7 +1687,7 @@
do {
var a = getCOWFastArray()
- var identity1 = a._rawIdentifier()
+ let identity1 = a._rawIdentifier()
let originalCapacity = a.capacity
expectEqual(3, a.count)
expectEqual(2, a[1])
@@ -327,13 +1700,13 @@
do {
var a1 = getCOWFastArray()
- var identity1 = a1._rawIdentifier()
+ let identity1 = a1._rawIdentifier()
expectEqual(3, a1.count)
expectEqual(2, a1[1])
var a2 = a1
a2.removeAll()
- var identity2 = a2._rawIdentifier()
+ let identity2 = a2._rawIdentifier()
expectEqual(identity1, a1._rawIdentifier())
expectNotEqual(identity2, identity1)
expectEqual(3, a1.count)
@@ -347,14 +1720,14 @@
do {
var a1 = getCOWFastArray()
- var identity1 = a1._rawIdentifier()
+ let identity1 = a1._rawIdentifier()
let originalCapacity = a1.capacity
expectEqual(3, a1.count)
expectEqual(2, a1[1])
var a2 = a1
a2.removeAll(keepingCapacity: true)
- var identity2 = a2._rawIdentifier()
+ let identity2 = a2._rawIdentifier()
expectEqual(identity1, a1._rawIdentifier())
expectNotEqual(identity2, identity1)
expectEqual(3, a1.count)
@@ -377,7 +1750,7 @@
expectEqual(2, a[1].value)
a.removeAll()
- var identity1 = a._rawIdentifier()
+ let identity1 = a._rawIdentifier()
expectLT(a.capacity, originalCapacity)
expectEqual(0, a.count)
expectEqual(identity1, a._rawIdentifier())
@@ -385,7 +1758,7 @@
do {
var a = getCOWSlowArray()
- var identity1 = a._rawIdentifier()
+ let identity1 = a._rawIdentifier()
let originalCapacity = a.capacity
expectEqual(3, a.count)
expectEqual(2, a[1].value)
@@ -398,13 +1771,13 @@
do {
var a1 = getCOWSlowArray()
- var identity1 = a1._rawIdentifier()
+ let identity1 = a1._rawIdentifier()
expectEqual(3, a1.count)
expectEqual(2, a1[1].value)
var a2 = a1
a2.removeAll()
- var identity2 = a2._rawIdentifier()
+ let identity2 = a2._rawIdentifier()
expectEqual(identity1, a1._rawIdentifier())
expectNotEqual(identity2, identity1)
expectEqual(3, a1.count)
@@ -418,14 +1791,14 @@
do {
var a1 = getCOWSlowArray()
- var identity1 = a1._rawIdentifier()
+ let identity1 = a1._rawIdentifier()
let originalCapacity = a1.capacity
expectEqual(3, a1.count)
expectEqual(2, a1[1].value)
var a2 = a1
a2.removeAll(keepingCapacity: true)
- var identity2 = a2._rawIdentifier()
+ let identity2 = a2._rawIdentifier()
expectEqual(identity1, a1._rawIdentifier())
expectNotEqual(identity2, identity1)
expectEqual(3, a1.count)
@@ -440,24 +1813,24 @@
}
ArrayTestSuite.test("COW.Fast.CountDoesNotReallocate") {
- var a = getCOWFastArray()
- var identity1 = a._rawIdentifier()
+ let a = getCOWFastArray()
+ let identity1 = a._rawIdentifier()
expectEqual(3, a.count)
expectEqual(identity1, a._rawIdentifier())
}
ArrayTestSuite.test("COW.Slow.CountDoesNotReallocate") {
- var a = getCOWSlowArray()
- var identity1 = a._rawIdentifier()
+ let a = getCOWSlowArray()
+ let identity1 = a._rawIdentifier()
expectEqual(3, a.count)
expectEqual(identity1, a._rawIdentifier())
}
ArrayTestSuite.test("COW.Fast.GenerateDoesNotReallocate") {
- var a = getCOWFastArray()
- var identity1 = a._rawIdentifier()
+ let a = getCOWFastArray()
+ let identity1 = a._rawIdentifier()
var iter = a.makeIterator()
var copy = Array<Int>()
@@ -469,8 +1842,8 @@
}
ArrayTestSuite.test("COW.Slow.GenerateDoesNotReallocate") {
- var a = getCOWSlowArray()
- var identity1 = a._rawIdentifier()
+ let a = getCOWSlowArray()
+ let identity1 = a._rawIdentifier()
var iter = a.makeIterator()
var copy = Array<Int>()
@@ -482,11 +1855,11 @@
}
ArrayTestSuite.test("COW.Fast.EqualityTestDoesNotReallocate") {
- var a1 = getCOWFastArray()
- var identity1 = a1._rawIdentifier()
+ let a1 = getCOWFastArray()
+ let identity1 = a1._rawIdentifier()
var a2 = getCOWFastArray()
- var identity2 = a2._rawIdentifier()
+ let identity2 = a2._rawIdentifier()
expectEqual(a1, a2)
expectEqual(identity1, a1._rawIdentifier())
@@ -499,11 +1872,11 @@
}
ArrayTestSuite.test("COW.Slow.EqualityTestDoesNotReallocate") {
- var a1 = getCOWSlowArray()
- var identity1 = a1._rawIdentifier()
+ let a1 = getCOWSlowArray()
+ let identity1 = a1._rawIdentifier()
var a2 = getCOWSlowArray()
- var identity2 = a2._rawIdentifier()
+ let identity2 = a2._rawIdentifier()
expectEqual(a1, a2)
expectEqual(identity1, a1._rawIdentifier())
@@ -1071,7 +2444,7 @@
.code {
let evil = EvilCollection(step, boundsChecked: evilBoundsCheck)
var a = Array((0..<200).lazy.map { LifetimeTracked($0) })
- var b = a
+ let b = a
if expectedToFail {
expectCrashLater()
}
diff --git a/validation-test/stdlib/Dictionary.swift b/validation-test/stdlib/Dictionary.swift
index d525909..b9262dd 100644
--- a/validation-test/stdlib/Dictionary.swift
+++ b/validation-test/stdlib/Dictionary.swift
@@ -2773,8 +2773,6 @@
pairs.append(kv)
}
assert(equalsUnordered(pairs, [ (10, 1010), (20, 1020), (30, 1030) ]))
- // The following is not required by the IteratorProtocol protocol, but
- // it is a nice QoI.
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
@@ -2793,8 +2791,6 @@
pairs.append(kv)
}
assert(equalsUnordered(pairs, [ (10, 1010), (20, 1020), (30, 1030) ]))
- // The following is not required by the IteratorProtocol protocol, but
- // it is a nice QoI.
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
@@ -2811,8 +2807,6 @@
// <rdar://problem/16811736> Optional tuples are broken as optionals regarding == comparison
// assert(iter.next() == .none)
assert(iter.next() == nil)
- // The following is not required by the IteratorProtocol protocol, but
- // it is a nice QoI.
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
@@ -2829,8 +2823,6 @@
// <rdar://problem/16811736> Optional tuples are broken as optionals regarding == comparison
// assert(iter.next() == .none)
assert(iter.next() == nil)
- // The following is not required by the IteratorProtocol protocol, but
- // it is a nice QoI.
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
@@ -2854,8 +2846,6 @@
expectedPairs += [(i, 1000 + i)]
}
assert(equalsUnordered(pairs, expectedPairs))
- // The following is not required by the IteratorProtocol protocol, but
- // it is a nice QoI.
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
@@ -2878,8 +2868,6 @@
expectedPairs += [(i, 1000 + i)]
}
assert(equalsUnordered(pairs, expectedPairs))
- // The following is not required by the IteratorProtocol protocol, but
- // it is a nice QoI.
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
@@ -2904,8 +2892,6 @@
}
var expectedPairs = [ (10, 1111), (20, 1111), (30, 1111), (40, 1111) ]
assert(equalsUnordered(pairs, expectedPairs))
- // The following is not required by the IteratorProtocol protocol, but
- // it is a nice QoI.
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
@@ -2930,8 +2916,6 @@
}
var expectedPairs = [ (10, 1111), (20, 1111), (30, 1111), (40, 1111) ]
assert(equalsUnordered(pairs, expectedPairs))
- // The following is not required by the IteratorProtocol protocol, but
- // it is a nice QoI.
assert(iter.next() == nil)
assert(iter.next() == nil)
assert(iter.next() == nil)
diff --git a/validation-test/stdlib/Set.swift b/validation-test/stdlib/Set.swift
index ed9fe61..b409796 100644
--- a/validation-test/stdlib/Set.swift
+++ b/validation-test/stdlib/Set.swift
@@ -1965,8 +1965,6 @@
members.append((member as! TestObjCKeyTy).value)
}
expectTrue(equalsUnordered(members, [1010, 2020, 3030]))
- // The following is not required by the IteratorProtocol protocol, but
- // it is a nice QoI.
expectNil(iter.next())
expectNil(iter.next())
expectNil(iter.next())
@@ -1984,8 +1982,6 @@
members.append(member.value)
}
expectTrue(equalsUnordered(members, [1010, 2020, 3030]))
- // The following is not required by the IteratorProtocol protocol, but
- // it is a nice QoI.
expectNil(iter.next())
expectNil(iter.next())
expectNil(iter.next())
@@ -1999,8 +1995,6 @@
var iter = s.makeIterator()
expectNil(iter.next())
- // The following is not required by the IteratorProtocol protocol, but
- // it is a nice QoI.
expectNil(iter.next())
expectNil(iter.next())
expectNil(iter.next())
@@ -2014,8 +2008,6 @@
var iter = s.makeIterator()
expectNil(iter.next())
- // The following is not required by the IteratorProtocol protocol, but
- // it is a nice QoI.
expectNil(iter.next())
expectNil(iter.next())
expectNil(iter.next())
@@ -2033,8 +2025,6 @@
members.append((member as! TestObjCKeyTy).value)
}
expectTrue(equalsUnordered(members, hugeNumberArray))
- // The following is not required by the IteratorProtocol protocol, but
- // it is a nice QoI.
expectNil(iter.next())
expectNil(iter.next())
expectNil(iter.next())
@@ -2052,8 +2042,6 @@
members.append((member as! TestBridgedKeyTy).value)
}
expectTrue(equalsUnordered(members, hugeNumberArray))
- // The following is not required by the IteratorProtocol protocol, but
- // it is a nice QoI.
expectNil(iter.next())
expectNil(iter.next())
expectNil(iter.next())