imerge 'github/tensorflow': automatic merge 147-9
diff --git a/cmake/caches/Runtime-Windows-x86_64.cmake b/cmake/caches/Runtime-Windows-x86_64.cmake
new file mode 100644
index 0000000..5fc88c2
--- /dev/null
+++ b/cmake/caches/Runtime-Windows-x86_64.cmake
@@ -0,0 +1,20 @@
+
+set(SWIFT_HOST_VARIANT_SDK WINDOWS CACHE STRING "")
+set(SWIFT_HOST_VARIANT_ARCH x86_64 CACHE STRING "")
+
+# NOTE(compnerd) disable the tools, we are trying to build just the standard
+# library.
+set(SWIFT_INCLUDE_TOOLS NO CACHE BOOL "")
+
+# NOTE(compnerd) cannot build tests since the tests require the toolchain
+set(SWIFT_INCLUDE_TESTS NO CACHE BOOL "")
+
+# NOTE(compnerd) cannot build docs since that requires perl
+set(SWIFT_INCLUDE_DOCS NO CACHE BOOL "")
+
+# NOTE(compnerd) these are part of the toolchain, not the runtime.
+set(SWIFT_BUILD_SYNTAXPARSERLIB NO CACHE BOOL "")
+set(SWIFT_BUILD_SOURCEKIT NO CACHE BOOL "")
+
+# NOTE(compnerd) build with the compiler specified, not a just built compiler.
+set(SWIFT_BUILD_RUNTIME_WITH_HOST_COMPILER YES CACHE BOOL "")
diff --git a/docs/WindowsBuild.md b/docs/WindowsBuild.md
index b66f30f..2d779b4 100644
--- a/docs/WindowsBuild.md
+++ b/docs/WindowsBuild.md
@@ -43,8 +43,8 @@
## Clone the repositories
-1. Clone `apple/llvm-project` into a directory for the toolchain
-2. Clone `apple/swift-cmark`, `apple/swift`, `apple/swift-corelibs-libdispatch`, `apple/swift-corelibs-foundation`, `apple/swift-corelibs-xctest`, `apple/swift-llbuild`, `apple/swift-package-manager` into the toolchain directory
+1. Clone `swift/master` branch of `apple/llvm-project` into the build workspace
+2. Clone `apple/swift-cmark`, `apple/swift`, `apple/swift-corelibs-libdispatch`, `apple/swift-corelibs-foundation`, `apple/swift-corelibs-xctest`, `apple/swift-tools-support-core`, `apple/swift-llbuild`, `apple/swift-argument-parser`, `apple/swift-driver`, `apple/swift-package-manager`, `JPSim/Yams`, `apple/indexstore-db` into the build workspace
- Currently, other repositories in the Swift project have not been tested and may not be supported.
@@ -310,12 +310,12 @@
-D Foundation_DIR=S:\b\3\cmake\modules ^
-D XCTest_DIR=S:\b\4\cmake\modules ^
-G Ninja ^
- -S S:\swift-llbuild
+ -S S:\Yams
ninja -C S:\b\7
```
-## Build swift-driver
+## Build swift-argument-parser
```cmd
cmake -B S:\b\8 ^
@@ -325,16 +325,14 @@
-D CMAKE_Swift_COMPILER=S:/b/1/bin/swiftc.exe ^
-D dispatch_DIR=S:\b\2\cmake\modules ^
-D Foundation_DIR=S:\b\3\cmake\modules ^
- -D TSC_DIR=S:\b\5\cmake\modules ^
- -D LLBuild_DIR=S:\b\6\cmake\modules ^
- -D Yams_DIR=S:\b\7\cmake\modules ^
+ -D XCTest_DIR=S:\b\4\cmake\modules ^
-G Ninja ^
- -S S:\swift-driver
+ -S S:\swift-argument-parser
ninja -C S:\b\8
```
-## Build swift-argument-parser
+## Build swift-driver
```cmd
cmake -B S:\b\9 ^
@@ -344,9 +342,12 @@
-D CMAKE_Swift_COMPILER=S:/b/1/bin/swiftc.exe ^
-D dispatch_DIR=S:\b\2\cmake\modules ^
-D Foundation_DIR=S:\b\3\cmake\modules ^
- -D XCTest_DIR=S:\b\4\cmake\modules ^
+ -D TSC_DIR=S:\b\5\cmake\modules ^
+ -D LLBuild_DIR=S:\b\6\cmake\modules ^
+ -D Yams_DIR=S:\b\7\cmake\modules ^
+ -D ArgumentParser_DIR=S:\b\8\cmake\modules ^
-G Ninja ^
- -S S:\swift-argument-parser
+ -S S:\swift-driver
ninja -C S:\b\9
```
@@ -365,8 +366,8 @@
-D TSC_DIR=S:\b\5\cmake\modules ^
-D LLBuild_DIR=S:\b\6\cmake\modules ^
-D Yams_DIR=S:\b\7\cmake\modules ^
- -D SwiftDriver_DIR=S:\b\8\cmake\modules ^
- -D ArgumentParser_DIR=S:\b\9\cmake\modules ^
+ -D ArgumentParser_DIR=S:\b\8\cmake\modules ^
+ -D SwiftDriver_DIR=S:\b\9\cmake\modules ^
-G Ninja ^
-S S:\swift-package-manager
@@ -383,7 +384,7 @@
- Run ninja install:
```cmd
-ninja -C S:\b\toolchain install
+ninja -C S:\b\1 install
```
- Add the Swift on Windows binaries path (`C:\Library\Developer\Toolchains\unknown-Asserts-development.xctoolchain\usr\bin`) to the `PATH` environment variable.
diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h
index 79df370..c8aa0bc 100644
--- a/include/swift/AST/ASTContext.h
+++ b/include/swift/AST/ASTContext.h
@@ -122,6 +122,7 @@
class IndexSubset;
struct SILAutoDiffDerivativeFunctionKey;
struct InterfaceSubContextDelegate;
+ class TypeCheckCompletionCallback;
enum class KnownProtocolKind : uint8_t;
@@ -258,6 +259,8 @@
/// Diags - The diagnostics engine.
DiagnosticEngine &Diags;
+ TypeCheckCompletionCallback *CompletionCallback = nullptr;
+
/// The request-evaluator that is used to process various requests.
Evaluator evaluator;
diff --git a/include/swift/AST/PlatformKinds.def b/include/swift/AST/PlatformKinds.def
index 29ae592..55d2f2e 100644
--- a/include/swift/AST/PlatformKinds.def
+++ b/include/swift/AST/PlatformKinds.def
@@ -32,5 +32,6 @@
AVAILABILITY_PLATFORM(macOSApplicationExtension, "application extensions for macOS")
AVAILABILITY_PLATFORM(macCatalyst, "Mac Catalyst")
AVAILABILITY_PLATFORM(macCatalystApplicationExtension, "application extensions for Mac Catalyst")
+AVAILABILITY_PLATFORM(OpenBSD, "OpenBSD")
#undef AVAILABILITY_PLATFORM
diff --git a/include/swift/IDE/CodeCompletion.h b/include/swift/IDE/CodeCompletion.h
index 4324cc9..60f1938 100644
--- a/include/swift/IDE/CodeCompletion.h
+++ b/include/swift/IDE/CodeCompletion.h
@@ -57,6 +57,20 @@
StringRef TokenName,
unsigned *CompletionOffset);
+StringRef copyString(llvm::BumpPtrAllocator &Allocator,
+ StringRef Str);
+
+const char *copyCString(llvm::BumpPtrAllocator &Allocator,
+ StringRef Str);
+
+template <typename T>
+ArrayRef<T> copyArray(llvm::BumpPtrAllocator &Allocator,
+ ArrayRef<T> Arr) {
+ T *Buffer = Allocator.Allocate<T>(Arr.size());
+ std::copy(Arr.begin(), Arr.end(), Buffer);
+ return llvm::makeArrayRef(Buffer, Arr.size());
+}
+
namespace detail {
class CodeCompletionStringChunk {
friend class swift::ide::CodeCompletionResultBuilder;
@@ -870,7 +884,7 @@
/// but should not hide any results.
SingleExpressionBody,
- /// There are known contextual types.
+ /// There are known contextual types, or there aren't but a nonvoid type is expected.
Required,
};
diff --git a/include/swift/Parse/CodeCompletionCallbacks.h b/include/swift/Parse/CodeCompletionCallbacks.h
index eeee748..d11c82e 100644
--- a/include/swift/Parse/CodeCompletionCallbacks.h
+++ b/include/swift/Parse/CodeCompletionCallbacks.h
@@ -119,7 +119,7 @@
virtual void setAttrTargetDeclKind(Optional<DeclKind> DK) {}
/// Complete expr-dot after we have consumed the dot.
- virtual void completeDotExpr(Expr *E, SourceLoc DotLoc) {};
+ virtual void completeDotExpr(CodeCompletionExpr *E, SourceLoc DotLoc) {};
/// Complete the beginning of a statement or expression.
virtual void completeStmtOrExpr(CodeCompletionExpr *E) {};
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index 9c258bc..fae3ada 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -692,6 +692,15 @@
Context.LangOpts.ParseForSyntaxTreeOnly;
}
+ /// If a function or closure body consists of a single expression, determine
+ /// whether we should turn wrap it in a return statement or not.
+ ///
+ /// We don't do this transformation for non-solver-based code completion
+ /// positions, as the source may be incomplete and the type mismatch in the
+ /// return statement will just confuse the type checker.
+ bool shouldSuppressSingleExpressionBodyTransform(
+ ParserStatus Status, MutableArrayRef<ASTNode> BodyElems);
+
public:
InFlightDiagnostic diagnose(SourceLoc Loc, Diagnostic Diag) {
if (Diags.isDiagnosticPointsToFirstBadToken(Diag.getID()) &&
diff --git a/include/swift/Sema/CodeCompletionTypeChecking.h b/include/swift/Sema/CodeCompletionTypeChecking.h
new file mode 100644
index 0000000..e461217
--- /dev/null
+++ b/include/swift/Sema/CodeCompletionTypeChecking.h
@@ -0,0 +1,83 @@
+//===--- CodeCompletionTypeChecking.h --------------------------*- C++ -*-===//
+//
+// Copyright (c) 2014 - 2020 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
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Provides TypeCheckCompletionCallback implementations for the various kinds
+/// of code completion. These extract and persist information needed to compute
+/// completion results from the solutions formed during expression typechecking.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_SEMA_CODECOMPLETIONTYPECHECKING_H
+#define SWIFT_SEMA_CODECOMPLETIONTYPECHECKING_H
+
+namespace swift {
+ class Decl;
+ class DeclContext;
+ class Type;
+ class ValueDecl;
+ class CodeCompletionExpr;
+
+ namespace constraints {
+ class Solution;
+ }
+
+ class TypeCheckCompletionCallback {
+ public:
+ /// Called for each solution produced while type-checking an expression
+ /// containing a code completion expression.
+ virtual void sawSolution(const constraints::Solution &solution) = 0;
+ virtual ~TypeCheckCompletionCallback() {}
+ };
+
+
+ /// Used to collect and store information needed to perform member completion
+ /// (\c CompletionKind::DotExpr ) from the solutions formed during expression
+ /// type-checking.
+ class DotExprTypeCheckCompletionCallback: public TypeCheckCompletionCallback {
+ public:
+ struct Result {
+ Type BaseTy;
+ ValueDecl* BaseDecl;
+ SmallVector<Type, 4> ExpectedTypes;
+ bool ExpectsNonVoid;
+ bool BaseIsStaticMetaType;
+ bool IsSingleExpressionBody;
+ };
+
+ private:
+ DeclContext *DC;
+ CodeCompletionExpr *CompletionExpr;
+ SmallVector<Result, 4> Results;
+ llvm::DenseMap<std::pair<Type, Decl*>, size_t> BaseToSolutionIdx;
+ bool GotCallback = false;
+
+ public:
+ DotExprTypeCheckCompletionCallback(DeclContext *DC,
+ CodeCompletionExpr *CompletionExpr)
+ : DC(DC), CompletionExpr(CompletionExpr) {}
+
+ /// Get the results collected from any sawSolutions() callbacks recevied so
+ /// far.
+ ArrayRef<Result> getResults() const { return Results; }
+
+ /// True if at least one solution was passed via the \c sawSolution
+ /// callback.
+ bool gotCallback() const { return GotCallback; }
+
+ /// Typecheck the code completion expression in isolation, calling
+ /// \c sawSolution for each solution formed.
+ void fallbackTypeCheck();
+
+ void sawSolution(const constraints::Solution &solution) override;
+ };
+}
+
+#endif
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 1bd4915..ac6fac8 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -4724,12 +4724,18 @@
// constraints while existential values do.
CanGenericSignature ASTContext::getOpenedArchetypeSignature(CanType existential,
ModuleDecl *mod) {
+ assert(existential.isExistentialType());
+
+ // The opened archetype signature for a protocol type is identical
+ // to the protocol's own canonical generic signature.
+ if (const auto protoTy = dyn_cast<ProtocolType>(existential)) {
+ return protoTy->getDecl()->getGenericSignature()->getCanonicalSignature();
+ }
+
auto found = getImpl().ExistentialSignatures.find(existential);
if (found != getImpl().ExistentialSignatures.end())
return found->second;
- assert(existential.isExistentialType());
-
auto genericParam = GenericTypeParamType::get(0, 0, *this);
Requirement requirement(RequirementKind::Conformance, genericParam,
existential);
diff --git a/lib/AST/PlatformKind.cpp b/lib/AST/PlatformKind.cpp
index ff6a003..f0f72ab 100644
--- a/lib/AST/PlatformKind.cpp
+++ b/lib/AST/PlatformKind.cpp
@@ -87,6 +87,8 @@
case PlatformKind::watchOS:
case PlatformKind::watchOSApplicationExtension:
return Target.isWatchOS();
+ case PlatformKind::OpenBSD:
+ return Target.isOSOpenBSD();
case PlatformKind::none:
llvm_unreachable("handled above");
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 402a33a..de2636f 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -3063,8 +3063,8 @@
}))
return maybeOpaqueType;
- // If the type still contains opaque types, recur.
- if (substTy->hasOpaqueArchetype()) {
+ // If the type changed, but still contains opaque types, recur.
+ if (!substTy->isEqual(maybeOpaqueType) && substTy->hasOpaqueArchetype()) {
return ::substOpaqueTypesWithUnderlyingTypes(
substTy, inContext, contextExpansion, isContextWholeModule);
}
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index e8081b5..ab2612c 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -1957,6 +1957,10 @@
"APIs deprecated as of macOS 10.9 and earlier are unavailable in Swift";
break;
+ case PlatformKind::OpenBSD:
+ deprecatedAsUnavailableMessage = "";
+ break;
+
case PlatformKind::none:
break;
}
@@ -1989,6 +1993,9 @@
case PlatformKind::watchOSApplicationExtension:
return name == "watchos" || name == "watchos_app_extension";
+ case PlatformKind::OpenBSD:
+ return name == "openbsd";
+
case PlatformKind::none:
return false;
}
@@ -2028,6 +2035,10 @@
case PlatformKind::watchOSApplicationExtension:
// No deprecation filter on watchOS
return false;
+
+ case PlatformKind::OpenBSD:
+ // No deprecation filter on OpenBSD
+ return false;
}
llvm_unreachable("Unexpected platform");
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index a1144c8..dc4656a 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -2217,6 +2217,7 @@
#endif
if (MergeModuleAction
+ && Args.hasArg(options::OPT_enable_library_evolution)
&& Args.hasFlag(options::OPT_verify_emitted_module_interface,
options::OPT_no_verify_emitted_module_interface,
verifyInterfacesByDefault)) {
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index 2ed0161..ef0e5cb 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -139,6 +139,24 @@
return buffer.data();
}
+/// This sorting function is used to stabilize the order in which dependencies
+/// are emitted into \c .d files that are consumed by external build systems.
+/// This serves to eliminate order as a source of non-determinism in these
+/// outputs.
+///
+/// The exact sorting predicate is not important. Currently, it is a
+/// lexicographic comparison that reverses the provided strings before applying
+/// the sorting predicate. This has the benefit of being somewhat
+/// invariant with respect to the installation location of various system
+/// components. e.g. on two systems, the same file identified by two different
+/// paths differing only in their relative install location such as
+///
+/// /Applications/MyXcode.app/Path/To/A/Framework/In/The/SDK/Header.h
+/// /Applications/Xcodes/AnotherXcode.app/Path/To/A/Framework/In/The/SDK/Header.h
+///
+/// should appear in roughly the same order relative to other paths. Ultimately,
+/// this makes it easier to test the contents of the emitted files with tools
+/// like FileCheck.
static std::vector<std::string>
reversePathSortedFilenames(const ArrayRef<std::string> elts) {
std::vector<std::string> tmp(elts.begin(), elts.end());
diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp
index 1cc5803..d6fe81c 100644
--- a/lib/IDE/CodeCompletion.cpp
+++ b/lib/IDE/CodeCompletion.cpp
@@ -35,6 +35,7 @@
#include "swift/IDE/Utils.h"
#include "swift/Parse/CodeCompletionCallbacks.h"
#include "swift/Sema/IDETypeChecking.h"
+#include "swift/Sema/CodeCompletionTypeChecking.h"
#include "swift/Syntax/SyntaxKind.h"
#include "swift/Strings.h"
#include "swift/Subsystems.h"
@@ -341,6 +342,21 @@
return CleanFile;
}
+llvm::StringRef swift::ide::copyString(llvm::BumpPtrAllocator &Allocator,
+ llvm::StringRef Str) {
+ char *Buffer = Allocator.Allocate<char>(Str.size());
+ std::copy(Str.begin(), Str.end(), Buffer);
+ return llvm::StringRef(Buffer, Str.size());
+}
+
+const char *swift::ide::copyCString(llvm::BumpPtrAllocator &Allocator,
+ llvm::StringRef Str) {
+ char *Buffer = Allocator.Allocate<char>(Str.size() + 1);
+ std::copy(Str.begin(), Str.end(), Buffer);
+ Buffer[Str.size()] = '\0';
+ return Buffer;
+}
+
CodeCompletionString::CodeCompletionString(ArrayRef<Chunk> Chunks) {
std::uninitialized_copy(Chunks.begin(), Chunks.end(),
getTrailingObjects<Chunk>());
@@ -769,29 +785,6 @@
llvm::errs() << "\n";
}
-static StringRef copyString(llvm::BumpPtrAllocator &Allocator,
- StringRef Str) {
- char *Mem = Allocator.Allocate<char>(Str.size());
- std::copy(Str.begin(), Str.end(), Mem);
- return StringRef(Mem, Str.size());
-}
-
-static ArrayRef<StringRef> copyStringArray(llvm::BumpPtrAllocator &Allocator,
- ArrayRef<StringRef> Arr) {
- StringRef *Buff = Allocator.Allocate<StringRef>(Arr.size());
- std::copy(Arr.begin(), Arr.end(), Buff);
- return llvm::makeArrayRef(Buff, Arr.size());
-}
-
-static ArrayRef<std::pair<StringRef, StringRef>> copyStringPairArray(
- llvm::BumpPtrAllocator &Allocator,
- ArrayRef<std::pair<StringRef, StringRef>> Arr) {
- std::pair<StringRef, StringRef> *Buff = Allocator.Allocate<std::pair<StringRef,
- StringRef>>(Arr.size());
- std::copy(Arr.begin(), Arr.end(), Buff);
- return llvm::makeArrayRef(Buff, Arr.size());
-}
-
void CodeCompletionResultBuilder::withNestedGroup(
CodeCompletionString::Chunk::ChunkKind Kind,
llvm::function_ref<void()> body) {
@@ -1125,7 +1118,7 @@
});
if (!USRs.empty())
- return copyStringArray(Allocator, USRs);
+ return copyArray(Allocator, ArrayRef<StringRef>(USRs));
return ArrayRef<StringRef>();
}
@@ -1162,7 +1155,7 @@
static CodeCompletionResult::ExpectedTypeRelation
calculateTypeRelationForDecl(const Decl *D, Type ExpectedType,
bool IsImplicitlyCurriedInstanceMethod,
- bool UseFuncResultType = true) {
+ bool UseFuncResultType){
auto VD = dyn_cast<ValueDecl>(D);
auto DC = D->getDeclContext();
if (!VD)
@@ -1197,9 +1190,9 @@
}
static CodeCompletionResult::ExpectedTypeRelation
-calculateMaxTypeRelationForDecl(
- const Decl *D, const ExpectedTypeContext &typeContext,
- bool IsImplicitlyCurriedInstanceMethod = false) {
+calculateMaxTypeRelationForDecl(const Decl *D,
+ const ExpectedTypeContext &typeContext,
+ bool IsImplicitlyCurriedInstanceMethod) {
if (typeContext.empty())
return CodeCompletionResult::ExpectedTypeRelation::Unknown;
@@ -1218,7 +1211,8 @@
continue;
Result = std::max(Result, calculateTypeRelationForDecl(
- D, Type, IsImplicitlyCurriedInstanceMethod));
+ D, Type, IsImplicitlyCurriedInstanceMethod,
+ /*UseFuncResultTy*/true));
// Map invalid -> unrelated when in a single-expression body, since the
// input may be incomplete.
@@ -1334,16 +1328,19 @@
}
auto typeRelation = ExpectedTypeRelation;
+ // FIXME: we don't actually have enough info to compute
+ // IsImplicitlyCurriedInstanceMethod here.
if (typeRelation == CodeCompletionResult::Unknown)
typeRelation =
- calculateMaxTypeRelationForDecl(AssociatedDecl, declTypeContext);
+ calculateMaxTypeRelationForDecl(AssociatedDecl, declTypeContext,
+ /*IsImplicitlyCurriedMethod*/false);
return new (*Sink.Allocator) CodeCompletionResult(
SemanticContext, NumBytesToErase, CCS, AssociatedDecl, ModuleName,
/*NotRecommended=*/IsNotRecommended, NotRecReason,
copyString(*Sink.Allocator, BriefComment),
copyAssociatedUSRs(*Sink.Allocator, AssociatedDecl),
- copyStringPairArray(*Sink.Allocator, CommentWords), typeRelation);
+ copyArray(*Sink.Allocator, CommentWords), typeRelation);
}
case CodeCompletionResult::ResultKind::Keyword:
@@ -1526,9 +1523,9 @@
}
namespace {
+
class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
CodeCompletionContext &CompletionContext;
- std::vector<RequestedCachedModule> RequestedModules;
CodeCompletionConsumer &Consumer;
CodeCompletionExpr *CodeCompleteTokenExpr = nullptr;
CompletionKind Kind = CompletionKind::None;
@@ -1660,7 +1657,7 @@
AttTargetDK = DK;
}
- void completeDotExpr(Expr *E, SourceLoc DotLoc) override;
+ void completeDotExpr(CodeCompletionExpr *E, SourceLoc DotLoc) override;
void completeStmtOrExpr(CodeCompletionExpr *E) override;
void completePostfixExprBeginning(CodeCompletionExpr *E) override;
void completeForEachSequenceBeginning(CodeCompletionExpr *E) override;
@@ -1709,7 +1706,7 @@
private:
void addKeywords(CodeCompletionResultSink &Sink, bool MaybeFuncBody);
- void deliverCompletionResults();
+ bool trySolverCompletion();
};
} // end anonymous namespace
@@ -2009,8 +2006,10 @@
IsStaticMetatype = value;
}
- void setExpectedTypes(ArrayRef<Type> Types, bool isSingleExpressionBody) {
+ void setExpectedTypes(ArrayRef<Type> Types, bool isSingleExpressionBody,
+ bool preferNonVoid = false) {
expectedTypeContext.isSingleExpressionBody = isSingleExpressionBody;
+ expectedTypeContext.preferNonVoid = preferNonVoid;
expectedTypeContext.possibleTypes.clear();
expectedTypeContext.possibleTypes.reserve(Types.size());
for (auto T : Types)
@@ -2023,7 +2022,7 @@
}
CodeCompletionContext::TypeContextKind typeContextKind() const {
- if (expectedTypeContext.empty()) {
+ if (expectedTypeContext.empty() && !expectedTypeContext.preferNonVoid) {
return CodeCompletionContext::TypeContextKind::None;
} else if (expectedTypeContext.isSingleExpressionBody) {
return CodeCompletionContext::TypeContextKind::SingleExpressionBody;
@@ -2040,8 +2039,8 @@
HaveLParen = Value;
}
- void setIsSuperRefExpr() {
- IsSuperRefExpr = true;
+ void setIsSuperRefExpr(bool Value = true) {
+ IsSuperRefExpr = Value;
}
void setIsSelfRefExpr(bool value) { IsSelfRefExpr = value; }
@@ -3047,6 +3046,12 @@
if (isUnresolvedMemberIdealType(ResultType))
Builder.setSemanticContext(SemanticContextKind::ExpressionSpecific);
+
+ if (!IsImplicitlyCurriedInstanceMethod &&
+ expectedTypeContext.requiresNonVoid() &&
+ ResultType->isVoid()) {
+ Builder.setExpectedTypeRelation(CodeCompletionResult::Invalid);
+ }
};
if (!AFT || IsImplicitlyCurriedInstanceMethod) {
@@ -5163,7 +5168,8 @@
addKeyword("setter", CodeCompletionKeywordKind::None);
}
-void CodeCompletionCallbacksImpl::completeDotExpr(Expr *E, SourceLoc DotLoc) {
+void CodeCompletionCallbacksImpl::completeDotExpr(CodeCompletionExpr *E,
+ SourceLoc DotLoc) {
assert(P.Tok.is(tok::code_complete));
// Don't produce any results in an enum element.
@@ -5176,9 +5182,10 @@
CompleteExprSelectorContext = ParseExprSelectorContext;
}
- ParsedExpr = E;
+ ParsedExpr = E->getBase();
this->DotLoc = DotLoc;
CurDeclContext = P.CurDeclContext;
+ CodeCompleteTokenExpr = E;
}
void CodeCompletionCallbacksImpl::completeStmtOrExpr(CodeCompletionExpr *E) {
@@ -5805,9 +5812,209 @@
}
}
+static void deliverCompletionResults(CodeCompletionContext &CompletionContext,
+ CompletionLookup &Lookup,
+ SourceFile &SF,
+ CodeCompletionConsumer &Consumer) {
+ llvm::SmallPtrSet<Identifier, 8> seenModuleNames;
+ std::vector<RequestedCachedModule> RequestedModules;
+
+ for (auto &Request: Lookup.RequestedCachedResults) {
+ llvm::DenseSet<CodeCompletionCache::Key> ImportsSeen;
+ auto handleImport = [&](ModuleDecl::ImportedModule Import) {
+ ModuleDecl *TheModule = Import.importedModule;
+ ModuleDecl::AccessPathTy Path = Import.accessPath;
+ if (TheModule->getFiles().empty())
+ return;
+
+ // Clang submodules are ignored and there's no lookup cost involved,
+ // so just ignore them and don't put the empty results in the cache
+ // because putting a lot of objects in the cache will push out
+ // other lookups.
+ if (isClangSubModule(TheModule))
+ return;
+
+ std::vector<std::string> AccessPath;
+ for (auto Piece : Path) {
+ AccessPath.push_back(std::string(Piece.Item));
+ }
+
+ StringRef ModuleFilename = TheModule->getModuleFilename();
+ // ModuleFilename can be empty if something strange happened during
+ // module loading, for example, the module file is corrupted.
+ if (!ModuleFilename.empty()) {
+ auto &Ctx = TheModule->getASTContext();
+ CodeCompletionCache::Key K{
+ ModuleFilename.str(),
+ std::string(TheModule->getName()),
+ AccessPath,
+ Request.NeedLeadingDot,
+ SF.hasTestableOrPrivateImport(
+ AccessLevel::Internal, TheModule,
+ SourceFile::ImportQueryKind::TestableOnly),
+ SF.hasTestableOrPrivateImport(
+ AccessLevel::Internal, TheModule,
+ SourceFile::ImportQueryKind::PrivateOnly),
+ Ctx.LangOpts.CodeCompleteInitsInPostfixExpr,
+ CompletionContext.getAnnotateResult(),
+ };
+
+ using PairType = llvm::DenseSet<swift::ide::CodeCompletionCache::Key,
+ llvm::DenseMapInfo<CodeCompletionCache::Key>>::iterator;
+ std::pair<PairType, bool> Result = ImportsSeen.insert(K);
+ if (!Result.second)
+ return; // already handled.
+ RequestedModules.push_back({std::move(K), TheModule,
+ Request.OnlyTypes, Request.OnlyPrecedenceGroups});
+
+ if (Request.IncludeModuleQualifier &&
+ seenModuleNames.insert(TheModule->getName()).second)
+ Lookup.addModuleName(TheModule);
+ }
+ };
+
+ if (Request.TheModule) {
+ // FIXME: actually check imports.
+ for (auto Import : namelookup::getAllImports(Request.TheModule)) {
+ handleImport(Import);
+ }
+ } else {
+ // Add results from current module.
+ Lookup.getToplevelCompletions(Request.OnlyTypes);
+
+ // Add the qualifying module name
+ auto curModule = SF.getParentModule();
+ if (Request.IncludeModuleQualifier &&
+ seenModuleNames.insert(curModule->getName()).second)
+ Lookup.addModuleName(curModule);
+
+ // Add results for all imported modules.
+ SmallVector<ModuleDecl::ImportedModule, 4> Imports;
+ SF.getImportedModules(
+ Imports, {ModuleDecl::ImportFilterKind::Public,
+ ModuleDecl::ImportFilterKind::Private,
+ ModuleDecl::ImportFilterKind::ImplementationOnly});
+
+ for (auto Imported : Imports) {
+ for (auto Import : namelookup::getAllImports(Imported.importedModule))
+ handleImport(Import);
+ }
+ }
+ }
+ Lookup.RequestedCachedResults.clear();
+ CompletionContext.typeContextKind = Lookup.typeContextKind();
+
+ // Use the current SourceFile as the DeclContext so that we can use it to
+ // perform qualified lookup, and to get the correct visibility for
+ // @testable imports.
+ DeclContext *DCForModules = &SF;
+ Consumer.handleResultsAndModules(CompletionContext, RequestedModules,
+ DCForModules);
+}
+
+void deliverDotExprResults(
+ ArrayRef<DotExprTypeCheckCompletionCallback::Result> Results,
+ Expr *BaseExpr, DeclContext *DC, SourceLoc DotLoc, bool IsInSelector,
+ ide::CodeCompletionContext &CompletionCtx,
+ CodeCompletionConsumer &Consumer) {
+ ASTContext &Ctx = DC->getASTContext();
+ CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC,
+ &CompletionCtx);
+
+ if (DotLoc.isValid())
+ Lookup.setHaveDot(DotLoc);
+
+ Lookup.setIsSuperRefExpr(isa<SuperRefExpr>(BaseExpr));
+
+ if (auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
+ Lookup.setIsSelfRefExpr(DRE->getDecl()->getName() == Ctx.Id_self);
+
+ if (isa<BindOptionalExpr>(BaseExpr) || isa<ForceValueExpr>(BaseExpr))
+ Lookup.setIsUnwrappedOptional(true);
+
+ if (IsInSelector) {
+ Lookup.includeInstanceMembers();
+ Lookup.setPreferFunctionReferencesToCalls();
+ }
+
+ for (auto &Result: Results) {
+ Lookup.setIsStaticMetatype(Result.BaseIsStaticMetaType);
+ Lookup.getPostfixKeywordCompletions(Result.BaseTy, BaseExpr);
+ Lookup.setExpectedTypes(Result.ExpectedTypes,
+ Result.IsSingleExpressionBody,
+ Result.ExpectsNonVoid);
+ if (isDynamicLookup(Result.BaseTy))
+ Lookup.setIsDynamicLookup();
+ Lookup.getValueExprCompletions(Result.BaseTy, Result.BaseDecl);
+ }
+
+ SourceFile *SF = DC->getParentSourceFile();
+ deliverCompletionResults(CompletionCtx, Lookup, *SF, Consumer);
+}
+
+bool CodeCompletionCallbacksImpl::trySolverCompletion() {
+ CompletionContext.CodeCompletionKind = Kind;
+
+ if (Kind == CompletionKind::None)
+ return true;
+
+ bool MaybeFuncBody = true;
+ if (CurDeclContext) {
+ auto *CD = CurDeclContext->getLocalContext();
+ if (!CD || CD->getContextKind() == DeclContextKind::Initializer ||
+ CD->getContextKind() == DeclContextKind::TopLevelCodeDecl)
+ MaybeFuncBody = false;
+ }
+
+ if (auto *DC = dyn_cast_or_null<DeclContext>(ParsedDecl)) {
+ if (DC->isChildContextOf(CurDeclContext))
+ CurDeclContext = DC;
+ }
+
+ assert(ParsedExpr || CurDeclContext);
+
+ SourceLoc CompletionLoc = ParsedExpr
+ ? ParsedExpr->getLoc()
+ : CurDeclContext->getASTContext().SourceMgr.getCodeCompletionLoc();
+
+ switch (Kind) {
+ case CompletionKind::DotExpr: {
+ assert(CodeCompleteTokenExpr);
+ assert(CurDeclContext);
+
+ DotExprTypeCheckCompletionCallback Lookup(CurDeclContext,
+ CodeCompleteTokenExpr);
+ llvm::SaveAndRestore<TypeCheckCompletionCallback*>
+ CompletionCollector(Context.CompletionCallback, &Lookup);
+ typeCheckContextAt(CurDeclContext, CompletionLoc);
+
+ // This (hopefully) only happens in cases where the expression isn't
+ // typechecked during normal compilation either (e.g. member completion in a
+ // switch case where there control expression is invalid). Having normal
+ // typechecking still resolve even these cases would be beneficial for
+ // tooling in general though.
+ if (!Lookup.gotCallback())
+ Lookup.fallbackTypeCheck();
+
+ addKeywords(CompletionContext.getResultSink(), MaybeFuncBody);
+
+ Expr *CheckedBase = CodeCompleteTokenExpr->getBase();
+ deliverDotExprResults(Lookup.getResults(), CheckedBase, CurDeclContext,
+ DotLoc, isInsideObjCSelector(), CompletionContext,
+ Consumer);
+ return true;
+ }
+ default:
+ return false;
+ }
+}
+
void CodeCompletionCallbacksImpl::doneParsing() {
CompletionContext.CodeCompletionKind = Kind;
+ if (trySolverCompletion())
+ return;
+
if (Kind == CompletionKind::None) {
return;
}
@@ -5881,27 +6088,10 @@
switch (Kind) {
case CompletionKind::None:
+ case CompletionKind::DotExpr:
llvm_unreachable("should be already handled");
return;
- case CompletionKind::DotExpr: {
- Lookup.setHaveDot(DotLoc);
-
- if (isDynamicLookup(*ExprType))
- Lookup.setIsDynamicLookup();
-
- Lookup.getPostfixKeywordCompletions(*ExprType, ParsedExpr);
-
- if (isa<BindOptionalExpr>(ParsedExpr) || isa<ForceValueExpr>(ParsedExpr))
- Lookup.setIsUnwrappedOptional(true);
-
- ExprContextInfo ContextInfo(CurDeclContext, ParsedExpr);
- Lookup.setExpectedTypes(ContextInfo.getPossibleTypes(),
- ContextInfo.isSingleExpressionBody());
- Lookup.getValueExprCompletions(*ExprType, ReferencedDecl.getDecl());
- break;
- }
-
case CompletionKind::KeyPathExprSwift: {
auto KPE = dyn_cast<KeyPathExpr>(ParsedExpr);
auto BGT = (*ExprType)->getAs<BoundGenericType>();
@@ -6329,112 +6519,7 @@
break;
}
- llvm::SmallPtrSet<Identifier, 8> seenModuleNames;
-
- for (auto &Request: Lookup.RequestedCachedResults) {
- // Use the current SourceFile as the DeclContext so that we can use it to
- // perform qualified lookup, and to get the correct visibility for
- // @testable imports.
- const SourceFile &SF = P.SF;
-
- llvm::DenseSet<CodeCompletionCache::Key> ImportsSeen;
- auto handleImport = [&](ModuleDecl::ImportedModule Import) {
- ModuleDecl *TheModule = Import.importedModule;
- ModuleDecl::AccessPathTy Path = Import.accessPath;
- if (TheModule->getFiles().empty())
- return;
-
- // Clang submodules are ignored and there's no lookup cost involved,
- // so just ignore them and don't put the empty results in the cache
- // because putting a lot of objects in the cache will push out
- // other lookups.
- if (isClangSubModule(TheModule))
- return;
-
- std::vector<std::string> AccessPath;
- for (auto Piece : Path) {
- AccessPath.push_back(std::string(Piece.Item));
- }
-
- StringRef ModuleFilename = TheModule->getModuleFilename();
- // ModuleFilename can be empty if something strange happened during
- // module loading, for example, the module file is corrupted.
- if (!ModuleFilename.empty()) {
- auto &Ctx = TheModule->getASTContext();
- CodeCompletionCache::Key K{
- ModuleFilename.str(),
- std::string(TheModule->getName()),
- AccessPath,
- Request.NeedLeadingDot,
- SF.hasTestableOrPrivateImport(
- AccessLevel::Internal, TheModule,
- SourceFile::ImportQueryKind::TestableOnly),
- SF.hasTestableOrPrivateImport(
- AccessLevel::Internal, TheModule,
- SourceFile::ImportQueryKind::PrivateOnly),
- Ctx.LangOpts.CodeCompleteInitsInPostfixExpr,
- CompletionContext.getAnnotateResult(),
- };
-
- using PairType = llvm::DenseSet<swift::ide::CodeCompletionCache::Key,
- llvm::DenseMapInfo<CodeCompletionCache::Key>>::iterator;
- std::pair<PairType, bool> Result = ImportsSeen.insert(K);
- if (!Result.second)
- return; // already handled.
- RequestedModules.push_back({std::move(K), TheModule,
- Request.OnlyTypes, Request.OnlyPrecedenceGroups});
-
- if (Request.IncludeModuleQualifier &&
- seenModuleNames.insert(TheModule->getName()).second)
- Lookup.addModuleName(TheModule);
- }
- };
-
- if (Request.TheModule) {
- // FIXME: actually check imports.
- for (auto Import : namelookup::getAllImports(Request.TheModule)) {
- handleImport(Import);
- }
- } else {
- // Add results from current module.
- Lookup.getToplevelCompletions(Request.OnlyTypes);
-
- // Add the qualifying module name
- auto curModule = CurDeclContext->getParentModule();
- if (Request.IncludeModuleQualifier &&
- seenModuleNames.insert(curModule->getName()).second)
- Lookup.addModuleName(curModule);
-
- // Add results for all imported modules.
- SmallVector<ModuleDecl::ImportedModule, 4> Imports;
- auto *SF = CurDeclContext->getParentSourceFile();
- SF->getImportedModules(
- Imports, {ModuleDecl::ImportFilterKind::Public,
- ModuleDecl::ImportFilterKind::Private,
- ModuleDecl::ImportFilterKind::ImplementationOnly});
-
- for (auto Imported : Imports) {
- for (auto Import : namelookup::getAllImports(Imported.importedModule))
- handleImport(Import);
- }
- }
- }
- Lookup.RequestedCachedResults.clear();
-
- CompletionContext.typeContextKind = Lookup.typeContextKind();
-
- deliverCompletionResults();
-}
-
-void CodeCompletionCallbacksImpl::deliverCompletionResults() {
- // Use the current SourceFile as the DeclContext so that we can use it to
- // perform qualified lookup, and to get the correct visibility for
- // @testable imports.
- DeclContext *DCForModules = &P.SF;
-
- Consumer.handleResultsAndModules(CompletionContext, RequestedModules,
- DCForModules);
- RequestedModules.clear();
+ deliverCompletionResults(CompletionContext, Lookup, P.SF, Consumer);
}
void PrintingCodeCompletionConsumer::handleResults(
diff --git a/lib/IDE/CodeCompletionCache.cpp b/lib/IDE/CodeCompletionCache.cpp
index 21a3d7a..ede2b04 100644
--- a/lib/IDE/CodeCompletionCache.cpp
+++ b/lib/IDE/CodeCompletionCache.cpp
@@ -102,28 +102,6 @@
/// cached results. This isn't expected to change very often.
static constexpr uint32_t onDiskCompletionCacheVersion = 1;
-static StringRef copyString(llvm::BumpPtrAllocator &Allocator, StringRef Str) {
- char *Mem = Allocator.Allocate<char>(Str.size());
- std::copy(Str.begin(), Str.end(), Mem);
- return StringRef(Mem, Str.size());
-}
-
-static ArrayRef<StringRef> copyStringArray(llvm::BumpPtrAllocator &Allocator,
- ArrayRef<StringRef> Arr) {
- StringRef *Buff = Allocator.Allocate<StringRef>(Arr.size());
- std::copy(Arr.begin(), Arr.end(), Buff);
- return llvm::makeArrayRef(Buff, Arr.size());
-}
-
-static ArrayRef<std::pair<StringRef, StringRef>> copyStringPairArray(
- llvm::BumpPtrAllocator &Allocator,
- ArrayRef<std::pair<StringRef, StringRef>> Arr) {
- std::pair<StringRef, StringRef> *Buff = Allocator.Allocate<std::pair<StringRef,
- StringRef>>(Arr.size());
- std::copy(Arr.begin(), Arr.end(), Buff);
- return llvm::makeArrayRef(Buff, Arr.size());
-}
-
/// Deserializes CodeCompletionResults from \p in and stores them in \p V.
/// \see writeCacheModule.
static bool readCachedModule(llvm::MemoryBuffer *in,
@@ -251,8 +229,8 @@
result = new (*V.Sink.Allocator) CodeCompletionResult(
context, numBytesToErase, string, declKind, isSystem, moduleName,
notRecommended, CodeCompletionResult::NotRecommendedReason::NoReason,
- briefDocComment, copyStringArray(*V.Sink.Allocator, assocUSRs),
- copyStringPairArray(*V.Sink.Allocator, declKeywords),
+ briefDocComment, copyArray(*V.Sink.Allocator, ArrayRef<StringRef>(assocUSRs)),
+ copyArray(*V.Sink.Allocator, ArrayRef<std::pair<StringRef, StringRef>>(declKeywords)),
CodeCompletionResult::Unknown, opKind);
} else {
result = new (*V.Sink.Allocator)
diff --git a/lib/IDE/CodeCompletionResultBuilder.h b/lib/IDE/CodeCompletionResultBuilder.h
index bb286e2..2e7babc 100644
--- a/lib/IDE/CodeCompletionResultBuilder.h
+++ b/lib/IDE/CodeCompletionResultBuilder.h
@@ -49,8 +49,20 @@
/// Since the input may be incomplete, we take into account that the types are
/// only a hint.
bool isSingleExpressionBody = false;
+ bool preferNonVoid = false;
bool empty() const { return possibleTypes.empty(); }
+ bool requiresNonVoid() const {
+ if (isSingleExpressionBody)
+ return false;
+ if (preferNonVoid)
+ return true;
+ if (possibleTypes.empty())
+ return false;
+ return std::all_of(possibleTypes.begin(), possibleTypes.end(), [](Type Ty) {
+ return !Ty->isVoid();
+ });
+ }
ExpectedTypeContext() = default;
ExpectedTypeContext(ArrayRef<Type> types, bool isSingleExpressionBody)
diff --git a/lib/IDE/ConformingMethodList.cpp b/lib/IDE/ConformingMethodList.cpp
index f1fcf9f..ae6cfce 100644
--- a/lib/IDE/ConformingMethodList.cpp
+++ b/lib/IDE/ConformingMethodList.cpp
@@ -45,16 +45,17 @@
// Only handle callbacks for suffix completions.
// {
- void completeDotExpr(Expr *E, SourceLoc DotLoc) override;
+ void completeDotExpr(CodeCompletionExpr *E, SourceLoc DotLoc) override;
void completePostfixExpr(Expr *E, bool hasSpace) override;
// }
void doneParsing() override;
};
-void ConformingMethodListCallbacks::completeDotExpr(Expr *E, SourceLoc DotLoc) {
+void ConformingMethodListCallbacks::completeDotExpr(CodeCompletionExpr *E,
+ SourceLoc DotLoc) {
CurDeclContext = P.CurDeclContext;
- ParsedExpr = E;
+ ParsedExpr = E->getBase();
}
void ConformingMethodListCallbacks::completePostfixExpr(Expr *E,
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 184fbac..7feccc2 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -21,6 +21,7 @@
#include "swift/Parse/SyntaxParsingContext.h"
#include "swift/Syntax/SyntaxKind.h"
#include "swift/Subsystems.h"
+#include "swift/AST/ASTWalker.h"
#include "swift/AST/Attr.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/DebuggerClient.h"
@@ -6467,10 +6468,10 @@
// If the body consists of a single expression, turn it into a return
// statement.
//
- // But don't do this transformation during code completion, as the source
- // may be incomplete and the type mismatch in return statement will just
- // confuse the type checker.
- if (BS->getNumElements() != 1 || Body.hasCodeCompletion())
+ // But don't do this transformation when performing certain kinds of code
+ // completion, as the source may be incomplete and the type mismatch in return
+ // statement will just confuse the type checker.
+ if (shouldSuppressSingleExpressionBodyTransform(Body, BS->getElements()))
return BS;
auto Element = BS->getFirstElement();
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index accdc19..8cf4c1b 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -15,6 +15,7 @@
//===----------------------------------------------------------------------===//
#include "swift/Parse/Parser.h"
+#include "swift/AST/ASTWalker.h"
#include "swift/AST/DiagnosticsParse.h"
#include "swift/AST/TypeRepr.h"
#include "swift/Basic/EditorPlaceholder.h"
@@ -1160,11 +1161,12 @@
// Handle "x.<tab>" for code completion.
if (Tok.is(tok::code_complete)) {
assert(!InSwiftKeyPath);
- if (CodeCompletion) {
- CodeCompletion->completeDotExpr(Result.get(), /*DotLoc=*/TokLoc);
- }
auto CCExpr = new (Context) CodeCompletionExpr(Result.get(),
- consumeToken(tok::code_complete));
+ Tok.getLoc());
+ if (CodeCompletion) {
+ CodeCompletion->completeDotExpr(CCExpr, /*DotLoc=*/TokLoc);
+ }
+ consumeToken(tok::code_complete);
return makeParserCodeCompletionResult(CCExpr);
}
@@ -2860,12 +2862,12 @@
// If the body consists of a single expression, turn it into a return
// statement.
//
- // But don't do this transformation during code completion, as the source
- // may be incomplete and the type mismatch in return statement will just
- // confuse the type checker.
+ // But don't do this transformation when performing certain kinds of code
+ // completion, as the source may be incomplete and the type mismatch in return
+ // statement will just confuse the type checker.
bool hasSingleExpressionBody = false;
- if (!missingRBrace && !Status.hasCodeCompletion() &&
- bodyElements.size() == 1) {
+ if (!missingRBrace &&
+ !shouldSuppressSingleExpressionBodyTransform(Status, bodyElements)) {
// If the closure's only body element is a single return statement,
// use that instead of creating a new wrapping return expression.
Expr *returnExpr = nullptr;
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 0028236..608a5ff 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -1185,6 +1185,34 @@
Segments.front().Length));
}
+bool Parser::
+shouldSuppressSingleExpressionBodyTransform(ParserStatus Status,
+ MutableArrayRef<ASTNode> BodyElems) {
+ if (BodyElems.size() != 1)
+ return true;
+
+ if (!Status.hasCodeCompletion())
+ return false;
+
+ struct HasMemberCompletion: public ASTWalker {
+ bool Value = false;
+ std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
+ if (auto *CCE = dyn_cast<CodeCompletionExpr>(E)) {
+ // If it has a base expression this is member completion, which is
+ // performed using the new solver-based mechanism, so it's ok to go
+ // ahead with the transform (and necessary to pick up the correct
+ // expected type).
+ Value = CCE->getBase();
+ return {false, nullptr};
+ }
+ return {true, E};
+ }
+ };
+ HasMemberCompletion Check;
+ BodyElems.front().walk(Check);
+ return !Check.Value;
+}
+
struct ParserUnit::Implementation {
std::shared_ptr<SyntaxParseActions> SPActions;
LangOptions LangOpts;
diff --git a/lib/PrintAsObjC/DeclAndTypePrinter.cpp b/lib/PrintAsObjC/DeclAndTypePrinter.cpp
index d380fec..bcdff13 100644
--- a/lib/PrintAsObjC/DeclAndTypePrinter.cpp
+++ b/lib/PrintAsObjC/DeclAndTypePrinter.cpp
@@ -878,6 +878,9 @@
case PlatformKind::watchOSApplicationExtension:
plat = "watchos_app_extension";
break;
+ case PlatformKind::OpenBSD:
+ plat = "openbsd";
+ break;
case PlatformKind::none:
llvm_unreachable("handled above");
}
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index cad8f08..2c34866 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -8419,6 +8419,15 @@
return ProtocolConformanceRef::forInvalid();
}
+bool Solution::hasType(ASTNode node) const {
+ auto result = nodeTypes.find(node);
+ if (result != nodeTypes.end())
+ return true;
+
+ auto &cs = getConstraintSystem();
+ return cs.hasType(node);
+}
+
Type Solution::getType(ASTNode node) const {
auto result = nodeTypes.find(node);
if (result != nodeTypes.end())
diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp
index a2cf838..7db71f6 100644
--- a/lib/Sema/CSBindings.cpp
+++ b/lib/Sema/CSBindings.cpp
@@ -360,6 +360,14 @@
if (locator->isLastElement<LocatorPathElt::MemberRefBase>())
PotentiallyIncomplete = true;
+ // Delay resolution of the code completion expression until
+ // the very end to give it a chance to be bound to some
+ // contextual type even if it's a hole.
+ if (locator->directlyAt<CodeCompletionExpr>()) {
+ FullyBound = true;
+ PotentiallyIncomplete = true;
+ }
+
addPotentialBinding(PotentialBinding::forHole(TypeVar, locator));
}
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index 1035ef1..cb8f547 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -1009,23 +1009,9 @@
virtual Type visitCodeCompletionExpr(CodeCompletionExpr *E) {
CS.Options |= ConstraintSystemFlags::SuppressDiagnostics;
auto locator = CS.getConstraintLocator(E);
- auto ty = CS.createTypeVariable(locator,
- TVO_CanBindToLValue |
- TVO_CanBindToNoEscape);
-
- // Defaults to the type of the base expression if we have a base
- // expression.
- // FIXME: This is just to keep the old behavior where `foo(base.<HERE>)`
- // the argument is type checked to the type of the 'base'. Ideally, code
- // completion expression should be defauled to 'UnresolvedType'
- // regardless of the existence of the base expression. But the constraint
- // system is simply not ready for that.
- if (auto base = E->getBase()) {
- CS.addConstraint(ConstraintKind::Defaultable, ty, CS.getType(base),
- locator);
- }
-
- return ty;
+ return CS.createTypeVariable(locator, TVO_CanBindToLValue |
+ TVO_CanBindToNoEscape |
+ TVO_CanBindToHole);
}
Type visitNilLiteralExpr(NilLiteralExpr *expr) {
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index afb594b..caae9b1 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -7168,18 +7168,19 @@
MemberLookupResult::ErrorAlreadyDiagnosed);
auto *fix = DefineMemberBasedOnUse::create(*this, baseTy, member,
alreadyDiagnosed, locator);
- // Impact is higher if the base is expected to be inferred from context,
- // because a failure to find a member ultimately means that base type is
- // not a match in this case.
- auto impact =
- locator->findLast<LocatorPathElt::UnresolvedMember>() ? 2 : 1;
+ auto instanceTy = baseObjTy->getMetatypeInstanceType();
+
+ auto impact = 2;
// Impact is higher if the the base type is any function type
// because function types can't have any members other than self
- if (baseObjTy->is<AnyFunctionType>()) {
- impact += 10;
+ if (instanceTy->is<AnyFunctionType>()) {
+ impact += 10;
}
+ if (instanceTy->isAny() || instanceTy->isAnyObject())
+ impact += 5;
+
if (recordFix(fix, impact))
return SolutionKind::Error;
diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp
index e48bf07..81c86b5 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -1406,48 +1406,47 @@
}
}
-void ConstraintSystem::solveForCodeCompletion(
- Expr *expr, DeclContext *DC, Type contextualType, ContextualTypePurpose CTP,
- llvm::function_ref<void(const Solution &)> callback) {
- // First, pre-check the expression, validating any types that occur in the
- // expression and folding sequence expressions.
- if (ConstraintSystem::preCheckExpression(
- expr, DC, /*replaceInvalidRefsWithErrors=*/true))
- return;
-
- ConstraintSystemOptions options;
- options |= ConstraintSystemFlags::AllowFixes;
- options |= ConstraintSystemFlags::SuppressDiagnostics;
-
- ConstraintSystem cs(DC, options);
-
- if (CTP != ContextualTypePurpose::CTP_Unused)
- cs.setContextualType(expr, TypeLoc::withoutLoc(contextualType), CTP);
+bool ConstraintSystem::solveForCodeCompletion(
+ SolutionApplicationTarget &target, SmallVectorImpl<Solution> &solutions) {
+ auto *expr = target.getAsExpr();
+ // Tell the constraint system what the contextual type is.
+ setContextualType(expr, target.getExprContextualTypeLoc(),
+ target.getExprContextualTypePurpose());
// Set up the expression type checker timer.
- cs.Timer.emplace(expr, cs);
+ Timer.emplace(expr, *this);
- cs.shrink(expr);
+ shrink(expr);
- if (!cs.generateConstraints(expr, DC))
- return;
+ if (isDebugMode()) {
+ auto &log = llvm::errs();
+ log << "--- Code Completion ---\n";
+ }
- llvm::SmallVector<Solution, 4> solutions;
+ if (generateConstraints(target, FreeTypeVariableBinding::Disallow))
+ return false;
{
- SolverState state(cs, FreeTypeVariableBinding::Disallow);
+ SolverState state(*this, FreeTypeVariableBinding::Disallow);
// Enable "diagnostic mode" by default, this means that
// solver would produce "fixed" solutions alongside valid
// ones, which helps code completion to rank choices.
state.recordFixes = true;
- cs.solveImpl(solutions);
+ solveImpl(solutions);
}
- for (const auto &solution : solutions) {
- callback(solution);
+ if (isDebugMode()) {
+ auto &log = llvm::errs();
+ log << "--- Discovered " << solutions.size() << " solutions ---\n";
+ for (const auto &solution : solutions) {
+ log << "--- Solution ---\n";
+ solution.dump(log);
+ }
}
+
+ return true;
}
void ConstraintSystem::collectDisjunctions(
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 4adce22..1612bfd 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -1190,6 +1190,8 @@
void setExprTypes(Expr *expr) const;
+ bool hasType(ASTNode node) const;
+
/// Retrieve the type of the given node, as recorded in this solution.
Type getType(ASTNode node) const;
@@ -5034,21 +5036,15 @@
/// solution, and constraint solver is allowed to produce partially correct
/// solutions. Such solutions can have any number of holes in them.
///
- /// \param expr The expression involved in code completion.
+ /// \param target The expression involved in code completion.
///
- /// \param DC The declaration context this expression is found in.
+ /// \param solutions The solutions produced for the given target without
+ /// filtering.
///
- /// \param contextualType The type \p expr is being converted to.
- ///
- /// \param CTP When contextualType is specified, this indicates what
- /// the conversion is doing.
- ///
- /// \param callback The callback to be used to provide results to
- /// code completion.
- static void
- solveForCodeCompletion(Expr *expr, DeclContext *DC, Type contextualType,
- ContextualTypePurpose CTP,
- llvm::function_ref<void(const Solution &)> callback);
+ /// \returns `false` if this call fails (e.g. pre-check or constraint
+ /// generation fails), `true` otherwise.
+ bool solveForCodeCompletion(SolutionApplicationTarget &target,
+ SmallVectorImpl<Solution> &solutions);
private:
/// Solve the system of constraints.
diff --git a/lib/Sema/TypeCheckCodeCompletion.cpp b/lib/Sema/TypeCheckCodeCompletion.cpp
index 6ba92ae..b78513e 100644
--- a/lib/Sema/TypeCheckCodeCompletion.cpp
+++ b/lib/Sema/TypeCheckCodeCompletion.cpp
@@ -41,6 +41,7 @@
#include "swift/Basic/STLExtras.h"
#include "swift/Parse/Lexer.h"
#include "swift/Sema/IDETypeChecking.h"
+#include "swift/Sema/CodeCompletionTypeChecking.h"
#include "swift/Strings.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
@@ -592,11 +593,25 @@
}
}
-void TypeChecker::typeCheckForCodeCompletion(
- Expr *expr, DeclContext *DC, Type contextualType, ContextualTypePurpose CTP,
+bool TypeChecker::typeCheckForCodeCompletion(
+ SolutionApplicationTarget &target,
llvm::function_ref<void(const Solution &)> callback) {
+ auto *DC = target.getDeclContext();
auto &Context = DC->getASTContext();
+ auto *expr = target.getAsExpr();
+ if (!expr)
+ return false;
+
+ // First of all, let's check whether given target expression
+ // does indeed have the code completion location in it.
+ {
+ auto range = expr->getSourceRange();
+ if (range.isInvalid() ||
+ !Context.SourceMgr.rangeContainsCodeCompletionLoc(range))
+ return false;
+ }
+
FrontendStatsTracer StatsTracer(Context.Stats,
"typecheck-for-code-completion", expr);
PrettyStackTraceExpr stackTrace(Context, "code-completion", expr);
@@ -604,8 +619,261 @@
expr = expr->walk(SanitizeExpr(Context,
/*shouldReusePrecheckedType=*/false));
- ConstraintSystem::solveForCodeCompletion(expr, DC, contextualType, CTP,
- callback);
+ enum class ContextKind {
+ Expression,
+ Application,
+ StringInterpolation,
+ SingleStmtClosure,
+ MultiStmtClosure,
+ ErrorExpression
+ };
+
+ class ContextFinder : public ASTWalker {
+ using Context = std::pair<ContextKind, Expr *>;
+
+ // Stack of all "interesting" contexts up to code completion expression.
+ llvm::SmallVector<Context, 4> Contexts;
+
+ Expr *CompletionExpr = nullptr;
+
+ public:
+ ContextFinder(Expr *E) {
+ Contexts.push_back(std::make_pair(ContextKind::Expression, E));
+ }
+
+ std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
+ if (auto *closure = dyn_cast<ClosureExpr>(E)) {
+ Contexts.push_back(std::make_pair(closure->hasSingleExpressionBody()
+ ? ContextKind::SingleStmtClosure
+ : ContextKind::MultiStmtClosure,
+ closure));
+ }
+
+ if (isa<InterpolatedStringLiteralExpr>(E)) {
+ Contexts.push_back(std::make_pair(ContextKind::StringInterpolation, E));
+ }
+
+ if (isa<ApplyExpr>(E)) {
+ Contexts.push_back(std::make_pair(ContextKind::Application, E));
+ }
+
+ if (isa<CodeCompletionExpr>(E)) {
+ CompletionExpr = E;
+ return std::make_pair(false, nullptr);
+ }
+
+ if (auto *Error = dyn_cast<ErrorExpr>(E)) {
+ Contexts.push_back(std::make_pair(ContextKind::ErrorExpression, E));
+ if (auto *OrigExpr = Error->getOriginalExpr()) {
+ OrigExpr->walk(*this);
+ return std::make_pair(false, hasCompletionExpr() ? nullptr : E);
+ }
+ }
+
+ return std::make_pair(true, E);
+ }
+
+ Expr *walkToExprPost(Expr *E) override {
+ if (isa<ClosureExpr>(E) || isa<InterpolatedStringLiteralExpr>(E) ||
+ isa<ApplyExpr>(E) || isa<ErrorExpr>(E))
+ Contexts.pop_back();
+ return E;
+ }
+
+ /// Check whether code completion expression is located inside of a
+ /// multi-statement closure.
+ bool locatedInMultiStmtClosure() const {
+ return hasContext(ContextKind::MultiStmtClosure);
+ }
+
+ bool locatedInStringIterpolation() const {
+ return hasContext(ContextKind::StringInterpolation);
+ }
+
+ bool hasCompletionExpr() const {
+ return CompletionExpr;
+ }
+
+ Expr *getCompletionExpr() const {
+ assert(CompletionExpr);
+ return CompletionExpr;
+ }
+
+ ErrorExpr *getInnermostErrorExpr() const {
+ for (const Context &curr : llvm::reverse(Contexts)) {
+ if (curr.first == ContextKind::ErrorExpression)
+ return cast<ErrorExpr>(curr.second);
+ }
+ return nullptr;
+ }
+
+ ClosureExpr *getOutermostMultiStmtClosure() const {
+ for (const Context &curr : Contexts) {
+ if (curr.first == ContextKind::MultiStmtClosure)
+ return cast<ClosureExpr>(curr.second);
+ }
+ return nullptr;
+ }
+
+ /// As a fallback sometimes its useful to not only type-check
+ /// code completion expression directly but instead add some
+ /// of the enclosing context e.g. when completion is an argument
+ /// to a call.
+ Expr *getCompletionExprInContext() const {
+ assert(CompletionExpr);
+
+ auto &innerContext = Contexts.back();
+ return innerContext.first == ContextKind::Application
+ ? innerContext.second
+ : CompletionExpr;
+ }
+
+ private:
+ bool hasContext(ContextKind kind) const {
+ return llvm::find_if(Contexts, [&kind](const Context &currContext) {
+ return currContext.first == kind;
+ }) != Contexts.end();
+ }
+ };
+
+ ContextFinder contextAnalyzer(expr);
+ expr->walk(contextAnalyzer);
+
+ // If there was no completion expr (e.g. if the code completion location was
+ // among tokens that were skipped over during parser error recovery) bail.
+ if (!contextAnalyzer.hasCompletionExpr())
+ return false;
+
+ // If the completion expression is in a valid subexpression of an ErrorExpr,
+ // fallback to trying the valid subexpression without any context. This can
+ // happen for cases like `expectsBoolArg(foo.<complete>).` which becomes an
+ // ErrorExpr due to the missing member name after the final dot.
+ if (auto *errorExpr = contextAnalyzer.getInnermostErrorExpr()) {
+ if (auto *origExpr = errorExpr->getOriginalExpr()) {
+ SolutionApplicationTarget completionTarget(origExpr, DC, CTP_Unused,
+ /*contextualType=*/Type(),
+ /*isDiscarded=*/true);
+ return typeCheckForCodeCompletion(completionTarget, callback);
+ }
+ }
+
+ // Interpolation components are type-checked separately.
+ if (contextAnalyzer.locatedInStringIterpolation())
+ return false;
+
+ // FIXME: There is currently no way to distinguish between
+ // multi-statement closures which are function builder bodies
+ // (that are type-checked together with enclosing context)
+ // and regular closures which are type-checked separately.
+
+ {
+ // First, pre-check the expression, validating any types that occur in the
+ // expression and folding sequence expressions.
+ auto failedPreCheck = ConstraintSystem::preCheckExpression(
+ expr, DC,
+ /*replaceInvalidRefsWithErrors=*/true);
+
+ target.setExpr(expr);
+
+ if (failedPreCheck)
+ return false;
+ }
+
+ enum class CompletionResult { Ok, NotApplicable, Fallback };
+
+ auto solveForCodeCompletion =
+ [&](SolutionApplicationTarget &target) -> CompletionResult {
+ ConstraintSystemOptions options;
+ options |= ConstraintSystemFlags::AllowFixes;
+ options |= ConstraintSystemFlags::SuppressDiagnostics;
+
+ ConstraintSystem cs(DC, options);
+
+ llvm::SmallVector<Solution, 4> solutions;
+
+ // If solve failed to generate constraints or with some other
+ // issue, we need to fallback to type-checking code completion
+ // expression directly.
+ if (!cs.solveForCodeCompletion(target, solutions))
+ return CompletionResult::Fallback;
+
+ // If case type-check didn't produce any solutions, let's
+ // attempt to type-check code completion expression without
+ // enclosing context.
+ if (solutions.empty())
+ return CompletionResult::Fallback;
+
+ // If code completion expression resides inside of multi-statement
+ // closure body it code either be type-checker together with context
+ // or not, it's impossible to say without trying. If solution
+ // doesn't have a type for a code completion expression it means that
+ // we have to wait until body of the closure is type-checked.
+ if (contextAnalyzer.locatedInMultiStmtClosure()) {
+ auto &solution = solutions.front();
+
+ // Let's check whether closure participated in the type-check.
+ if (solution.hasType(contextAnalyzer.getCompletionExpr())) {
+ llvm::for_each(solutions, callback);
+ return CompletionResult::Ok;
+ }
+
+ if (solutions.size() > 1)
+ return CompletionResult::Fallback;
+
+ auto *closure = contextAnalyzer.getOutermostMultiStmtClosure();
+ auto closureType = solution.getResolvedType(closure);
+
+ if (closureType->hasUnresolvedType())
+ return CompletionResult::Fallback;
+
+ return CompletionResult::NotApplicable;
+ }
+
+ llvm::for_each(solutions, callback);
+ return CompletionResult::Ok;
+ };
+
+ switch (solveForCodeCompletion(target)) {
+ case CompletionResult::Ok:
+ return true;
+
+ case CompletionResult::NotApplicable:
+ return false;
+
+ case CompletionResult::Fallback:
+ break;
+ }
+
+ {
+ auto *completionExpr = contextAnalyzer.getCompletionExpr();
+
+ if (contextAnalyzer.locatedInMultiStmtClosure()) {
+ auto completionInContext = contextAnalyzer.getCompletionExprInContext();
+ // If pre-check fails, let's switch to code completion
+ // expression without any enclosing context.
+ if (ConstraintSystem::preCheckExpression(
+ completionInContext, DC, /*replaceInvalidRefsWithErrors=*/true)) {
+ completionExpr = contextAnalyzer.getCompletionExpr();
+ } else {
+ completionExpr = completionInContext;
+ }
+ }
+
+ // If initial solve failed, let's fallback to checking only code completion
+ // expresion without any context.
+ SolutionApplicationTarget completionTarget(completionExpr, DC, CTP_Unused,
+ /*contextualType=*/Type(),
+ /*isDiscarded=*/true);
+
+ switch (solveForCodeCompletion(completionTarget)) {
+ case CompletionResult::Ok:
+ case CompletionResult::Fallback:
+ break;
+ case CompletionResult::NotApplicable:
+ llvm_unreachable("solve on CodeCompletionExpr produced not applicable?");
+ }
+ }
+ return true;
}
static Optional<Type> getTypeOfCompletionContextExpr(
@@ -703,3 +971,115 @@
swift::lookupSemanticMember(DeclContext *DC, Type ty, DeclName name) {
return TypeChecker::lookupMember(DC, ty, DeclNameRef(name), None);
}
+
+void DotExprTypeCheckCompletionCallback::fallbackTypeCheck() {
+ assert(!gotCallback());
+ SolutionApplicationTarget completionTarget(CompletionExpr, DC, CTP_Unused,
+ Type(), /*isDiscared=*/true);
+ TypeChecker::typeCheckForCodeCompletion(
+ completionTarget, [&](const Solution &S) { sawSolution(S); });
+}
+
+void DotExprTypeCheckCompletionCallback::
+sawSolution(const constraints::Solution &S) {
+ GotCallback = true;
+ auto &CS = S.getConstraintSystem();
+
+ auto GetType = [&](Expr *E) {
+ // To aid code completion, we need to attempt to convert type holes
+ // back into underlying generic parameters if possible, since type
+ // of the code completion expression is used as "expected" (or contextual)
+ // type so it's helpful to know what requirements it has to filter
+ // the list of possible member candidates e.g.
+ //
+ // \code
+ // func test<T: P>(_: [T]) {}
+ //
+ // test(42.#^MEMBERS^#)
+ // \code
+ //
+ // It's impossible to resolve `T` in this case but code completion
+ // expression should still have a type of `[T]` instead of `[<<hole>>]`
+ // because it helps to produce correct contextual member list based on
+ // a conformance requirement associated with generic parameter `T`.
+ if (isa<CodeCompletionExpr>(E)) {
+ auto completionTy = S.getType(E).transform([&](Type type) -> Type {
+ if (auto *typeVar = type->getAs<TypeVariableType>())
+ return S.getFixedType(typeVar);
+ return type;
+ });
+
+ return S.simplifyType(completionTy.transform([&](Type type) {
+ if (auto *hole = type->getAs<HoleType>()) {
+ if (auto *typeVar =
+ hole->getOriginatorType().dyn_cast<TypeVariableType *>()) {
+ if (auto *GP = typeVar->getImpl().getGenericParameter()) {
+ // Code completion depends on generic parameter type being
+ // represented in terms of `ArchetypeType` since it's easy
+ // to extract protocol requirements from it.
+ if (auto *GPD = GP->getDecl())
+ return GPD->getInnermostDeclContext()->mapTypeIntoContext(GP);
+ }
+ }
+
+ return Type(CS.getASTContext().TheUnresolvedType);
+ }
+
+ return type;
+ }));
+ }
+
+ return S.getResolvedType(E);
+ };
+
+ auto *ParsedExpr = CompletionExpr->getBase();
+ auto *SemanticExpr = ParsedExpr->getSemanticsProvidingExpr();
+
+ auto BaseTy = GetType(ParsedExpr);
+ // If base type couldn't be determined (e.g. because base expression
+ // is an invalid reference), let's not attempt to do a lookup since
+ // it wouldn't produce any useful results anyway.
+ if (!BaseTy || BaseTy->is<UnresolvedType>())
+ return;
+
+ auto *Locator = CS.getConstraintLocator(SemanticExpr);
+ Type ExpectedTy = GetType(CompletionExpr);
+ Expr *ParentExpr = CS.getParentExpr(CompletionExpr);
+ if (!ParentExpr)
+ ExpectedTy = CS.getContextualType(CompletionExpr);
+
+ auto *CalleeLocator = S.getCalleeLocator(Locator);
+ ValueDecl *ReferencedDecl = nullptr;
+ if (auto SelectedOverload = S.getOverloadChoiceIfAvailable(CalleeLocator))
+ ReferencedDecl = SelectedOverload->choice.getDeclOrNull();
+
+ auto Key = std::make_pair(BaseTy, ReferencedDecl);
+ auto Ret = BaseToSolutionIdx.insert({Key, Results.size()});
+ if (!Ret.second && ExpectedTy) {
+ Results[Ret.first->getSecond()].ExpectedTypes.push_back(ExpectedTy);
+ } else {
+ bool ISDMT = S.isStaticallyDerivedMetatype(ParsedExpr);
+ bool SingleExprBody = false;
+ bool DisallowVoid = ExpectedTy
+ ? !ExpectedTy->isVoid()
+ : !ParentExpr && CS.getContextualTypePurpose(
+ CompletionExpr) != CTP_Unused;
+
+ if (!ParentExpr) {
+ if (CS.getContextualTypePurpose(CompletionExpr) == CTP_ReturnSingleExpr)
+ SingleExprBody = true;
+ } else if (auto *ParentCE = dyn_cast<ClosureExpr>(ParentExpr)) {
+ if (ParentCE->hasSingleExpressionBody() &&
+ ParentCE->getSingleExpressionBody() == CompletionExpr) {
+ ASTNode Last = ParentCE->getBody()->getLastElement();
+ if (!Last.isStmt(StmtKind::Return) || Last.isImplicit())
+ SingleExprBody = true;
+ }
+ }
+
+ Results.push_back(
+ {BaseTy, ReferencedDecl, {}, DisallowVoid, ISDMT, SingleExprBody});
+ if (ExpectedTy)
+ Results.back().ExpectedTypes.push_back(ExpectedTy);
+ }
+}
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index 8908b48..5e35f39 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -39,6 +39,7 @@
#include "swift/Basic/Statistic.h"
#include "swift/Parse/Confusables.h"
#include "swift/Parse/Lexer.h"
+#include "swift/Sema/CodeCompletionTypeChecking.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
@@ -2164,6 +2165,14 @@
"typecheck-expr", expr);
PrettyStackTraceExpr stackTrace(Context, "type-checking", expr);
+ // First let's check whether given expression has a code completion
+ // token which requires special handling.
+ if (Context.CompletionCallback &&
+ typeCheckForCodeCompletion(target, [&](const constraints::Solution &S) {
+ Context.CompletionCallback->sawSolution(S);
+ }))
+ return None;
+
// First, pre-check the expression, validating any types that occur in the
// expression and folding sequence expressions.
if (ConstraintSystem::preCheckExpression(
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index 27509f4..e758492 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -1917,6 +1917,11 @@
// Wire up the function body now.
func->setBody(*optBody, AbstractFunctionDecl::BodyKind::TypeChecked);
return false;
+ } else if (func->hasSingleExpressionBody() &&
+ func->getResultInterfaceType()->isVoid()) {
+ // The function returns void. We don't need an explicit return, no matter
+ // what the type of the expression is. Take the inserted return back out.
+ func->getBody()->setFirstElement(func->getSingleExpressionBody());
}
}
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 493470b..38ffdd0 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -636,8 +636,11 @@
/// it doesn't mutate given expression, even if there is a single valid
/// solution, and constraint solver is allowed to produce partially correct
/// solutions. Such solutions can have any number of holes in them.
-void typeCheckForCodeCompletion(
- Expr *expr, DeclContext *DC, Type contextualType, ContextualTypePurpose CTP,
+///
+/// \returns `true` if target was applicable and it was possible to infer
+/// types for code completion, `false` othrewise.
+bool typeCheckForCodeCompletion(
+ constraints::SolutionApplicationTarget &target,
llvm::function_ref<void(const constraints::Solution &)> callback);
/// Check the key-path expression.
diff --git a/lib/Serialization/ModuleFileSharedCore.h b/lib/Serialization/ModuleFileSharedCore.h
index 2caa4a3..3277578 100644
--- a/lib/Serialization/ModuleFileSharedCore.h
+++ b/lib/Serialization/ModuleFileSharedCore.h
@@ -456,7 +456,6 @@
/// \param isFramework If true, this is treated as a framework module for
/// linking purposes.
/// \param[out] theModule The loaded module.
- /// \param[out] extInfo Optionally, extra info serialized about the module.
/// \returns Whether the module was successfully loaded, or what went wrong
/// if it was not.
static serialization::ValidationInfo
diff --git a/lib/SymbolGraphGen/AvailabilityMixin.cpp b/lib/SymbolGraphGen/AvailabilityMixin.cpp
index aa446f4..4dc66f0 100644
--- a/lib/SymbolGraphGen/AvailabilityMixin.cpp
+++ b/lib/SymbolGraphGen/AvailabilityMixin.cpp
@@ -56,6 +56,8 @@
return { "tvOSAppExtension" };
case swift::PlatformKind::watchOSApplicationExtension:
return { "watchOSAppExtension" };
+ case swift::PlatformKind::OpenBSD:
+ return { "OpenBSD" };
case swift::PlatformKind::none:
return { "*" };
}
diff --git a/lib/TBDGen/TBDGen.cpp b/lib/TBDGen/TBDGen.cpp
index 623e3d0..e3523a6 100644
--- a/lib/TBDGen/TBDGen.cpp
+++ b/lib/TBDGen/TBDGen.cpp
@@ -249,6 +249,8 @@
switch(Ver.Platform) {
case swift::PlatformKind::none:
llvm_unreachable("cannot find platform kind");
+ case swift::PlatformKind::OpenBSD:
+ llvm_unreachable("not used for this platform");
case swift::PlatformKind::iOS:
case swift::PlatformKind::iOSApplicationExtension:
return Ver.IsSimulator ? LinkerPlatformId::iOS_sim:
diff --git a/stdlib/cmake/modules/AddSwiftStdlib.cmake b/stdlib/cmake/modules/AddSwiftStdlib.cmake
index 2332ad6..1cff522 100644
--- a/stdlib/cmake/modules/AddSwiftStdlib.cmake
+++ b/stdlib/cmake/modules/AddSwiftStdlib.cmake
@@ -298,6 +298,9 @@
list(APPEND result "-DSWIFT_OBJC_INTEROP=0")
endif()
+ # TODO(mracek): This should get turned off for non-ABI-stable environments.
+ list(APPEND result "-DSWIFT_LIBRARY_EVOLUTION=1")
+
if(NOT SWIFT_ENABLE_COMPATIBILITY_OVERRIDES)
list(APPEND result "-DSWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES")
endif()
diff --git a/stdlib/public/Platform/winsdk.modulemap b/stdlib/public/Platform/winsdk.modulemap
index fc0d961..97acd81 100644
--- a/stdlib/public/Platform/winsdk.modulemap
+++ b/stdlib/public/Platform/winsdk.modulemap
@@ -180,9 +180,11 @@
}
module ShellAPI {
+ header "shellapi.h"
header "Shlwapi.h"
export *
+ link "shell32.lib"
link "ShLwApi.Lib"
}
diff --git a/stdlib/public/core/BridgingBuffer.swift b/stdlib/public/core/BridgingBuffer.swift
index c3d0613..5e6e28a 100644
--- a/stdlib/public/core/BridgingBuffer.swift
+++ b/stdlib/public/core/BridgingBuffer.swift
@@ -25,6 +25,7 @@
internal typealias _BridgingBuffer
= ManagedBufferPointer<_BridgingBufferHeader, AnyObject>
+@available(OpenBSD, unavailable, message: "malloc_size is unavailable.")
extension ManagedBufferPointer
where Header == _BridgingBufferHeader, Element == AnyObject {
internal init(_ count: Int) {
diff --git a/stdlib/public/core/FloatingPoint.swift b/stdlib/public/core/FloatingPoint.swift
index 9f93166..80b3249 100644
--- a/stdlib/public/core/FloatingPoint.swift
+++ b/stdlib/public/core/FloatingPoint.swift
@@ -1890,21 +1890,48 @@
/// - Parameter value: A floating-point value to be converted.
@inlinable
public init<Source: BinaryFloatingPoint>(_ value: Source) {
+ // If two IEEE 754 binary interchange formats share the same exponent bit
+ // count and significand bit count, then they must share the same encoding
+ // for finite and infinite values.
+ switch (Source.exponentBitCount, Source.significandBitCount) {
#if !os(macOS) && !(os(iOS) && targetEnvironment(macCatalyst))
- if #available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) {
- if case let value_ as Float16 = value {
- self = Self(Float(value_))
- return
+ case (5, 10):
+ guard #available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) else {
+ self = Self._convert(from: value).value
+ break
}
- }
+ let value_ = value as? Float16 ?? Float16(
+ sign: value.sign,
+ exponentBitPattern:
+ UInt(truncatingIfNeeded: value.exponentBitPattern),
+ significandBitPattern:
+ UInt16(truncatingIfNeeded: value.significandBitPattern))
+ self = Self(Float(value_))
#endif
- switch value {
- case let value_ as Float:
+ case (8, 23):
+ let value_ = value as? Float ?? Float(
+ sign: value.sign,
+ exponentBitPattern:
+ UInt(truncatingIfNeeded: value.exponentBitPattern),
+ significandBitPattern:
+ UInt32(truncatingIfNeeded: value.significandBitPattern))
self = Self(value_)
- case let value_ as Double:
+ case (11, 52):
+ let value_ = value as? Double ?? Double(
+ sign: value.sign,
+ exponentBitPattern:
+ UInt(truncatingIfNeeded: value.exponentBitPattern),
+ significandBitPattern:
+ UInt64(truncatingIfNeeded: value.significandBitPattern))
self = Self(value_)
#if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64))
- case let value_ as Float80:
+ case (15, 63):
+ let value_ = value as? Float80 ?? Float80(
+ sign: value.sign,
+ exponentBitPattern:
+ UInt(truncatingIfNeeded: value.exponentBitPattern),
+ significandBitPattern:
+ UInt64(truncatingIfNeeded: value.significandBitPattern))
self = Self(value_)
#endif
default:
diff --git a/stdlib/public/core/ManagedBuffer.swift b/stdlib/public/core/ManagedBuffer.swift
index 6248994..bb6a632 100644
--- a/stdlib/public/core/ManagedBuffer.swift
+++ b/stdlib/public/core/ManagedBuffer.swift
@@ -83,6 +83,7 @@
/// idea to store this information in the "header" area when
/// an instance is created.
@inlinable
+ @available(OpenBSD, unavailable, message: "malloc_size is unavailable.")
public final var capacity: Int {
let storageAddr = UnsafeMutableRawPointer(Builtin.bridgeToRawPointer(self))
let endAddr = storageAddr + _swift_stdlib_malloc_size(storageAddr)
@@ -197,6 +198,7 @@
/// properties. The `deinit` of `bufferClass` must destroy its
/// stored `Header` and any constructed `Element`s.
@inlinable
+ @available(OpenBSD, unavailable, message: "malloc_size is unavailable.")
public init(
bufferClass: AnyClass,
minimumCapacity: Int,
@@ -329,6 +331,7 @@
/// idea to store this information in the "header" area when
/// an instance is created.
@inlinable
+ @available(OpenBSD, unavailable, message: "malloc_size is unavailable.")
public var capacity: Int {
return (
_capacityInBytes &- ManagedBufferPointer._elementOffset
@@ -431,6 +434,7 @@
/// The actual number of bytes allocated for this object.
@inlinable
+ @available(OpenBSD, unavailable, message: "malloc_size is unavailable.")
internal var _capacityInBytes: Int {
return _swift_stdlib_malloc_size(_address)
}
diff --git a/stdlib/public/core/VarArgs.swift b/stdlib/public/core/VarArgs.swift
index 8576a86..40a134b 100644
--- a/stdlib/public/core/VarArgs.swift
+++ b/stdlib/public/core/VarArgs.swift
@@ -63,6 +63,17 @@
var _cVarArgAlignment: Int { get }
}
+#if !_runtime(_ObjC)
+/// Some pointers require an alternate object to be retained. The object
+/// that is returned will be used with _cVarArgEncoding and held until
+/// the closure is complete. This is required since autoreleased storage
+/// is not available on all platforms.
+public protocol _CVarArgObject: CVarArg {
+ /// Returns the alternate object that should be encoded.
+ var _cVarArgObject: CVarArg { get }
+}
+#endif
+
#if arch(x86_64)
@usableFromInline
internal let _countGPRegisters = 6
@@ -462,6 +473,11 @@
@usableFromInline // c-abi
internal var storage: ContiguousArray<Int>
+#if !_runtime(_ObjC)
+ @usableFromInline // c-abi
+ internal var retainer = [CVarArg]()
+#endif
+
@inlinable // c-abi
internal init() {
// prepare the register save area
@@ -473,6 +489,16 @@
@inlinable // c-abi
internal func append(_ arg: CVarArg) {
+#if !_runtime(_ObjC)
+ var arg = arg
+
+ // We may need to retain an object that provides a pointer value.
+ if let obj = arg as? _CVarArgObject {
+ arg = obj._cVarArgObject
+ retainer.append(arg)
+ }
+#endif
+
var encoded = arg._cVarArgEncoding
#if arch(x86_64) || arch(arm64)
@@ -560,6 +586,16 @@
@inlinable // c-abi
internal func append(_ arg: CVarArg) {
+#if !_runtime(_ObjC)
+ var arg = arg
+
+ // We may need to retain an object that provides a pointer value.
+ if let obj = arg as? _CVarArgObject {
+ arg = obj._cVarArgObject
+ retainer.append(arg)
+ }
+#endif
+
// Write alignment padding if necessary.
// This is needed on architectures where the ABI alignment of some
// supported vararg type is greater than the alignment of Int, such
@@ -665,6 +701,11 @@
@usableFromInline // c-abi
internal var storage: UnsafeMutablePointer<Int>?
+#if !_runtime(_ObjC)
+ @usableFromInline // c-abi
+ internal var retainer = [CVarArg]()
+#endif
+
internal static var alignedStorageForEmptyVaLists: Double = 0
}
diff --git a/stdlib/public/runtime/DynamicCast.cpp b/stdlib/public/runtime/DynamicCast.cpp
index fa628e2..f848000 100644
--- a/stdlib/public/runtime/DynamicCast.cpp
+++ b/stdlib/public/runtime/DynamicCast.cpp
@@ -145,6 +145,9 @@
// protocol _ObjectiveCBridgeable {
struct _ObjectiveCBridgeableWitnessTable : WitnessTable {
+ #define _protocolWitnessSignedPointer(n) \
+ __ptrauth_swift_protocol_witness_function_pointer(SpecialPointerAuthDiscriminators::n##Discriminator) n
+
static_assert(WitnessTableFirstRequirementOffset == 1,
"Witness table layout changed");
@@ -153,14 +156,14 @@
// func _bridgeToObjectiveC() -> _ObjectiveCType
SWIFT_CC(swift)
- HeapObject *(*bridgeToObjectiveC)(
+ HeapObject *(*_protocolWitnessSignedPointer(bridgeToObjectiveC))(
SWIFT_CONTEXT OpaqueValue *self, const Metadata *Self,
const _ObjectiveCBridgeableWitnessTable *witnessTable);
// class func _forceBridgeFromObjectiveC(x: _ObjectiveCType,
// inout result: Self?)
SWIFT_CC(swift)
- void (*forceBridgeFromObjectiveC)(
+ void (*_protocolWitnessSignedPointer(forceBridgeFromObjectiveC))(
HeapObject *sourceValue,
OpaqueValue *result,
SWIFT_CONTEXT const Metadata *self,
@@ -170,7 +173,7 @@
// class func _conditionallyBridgeFromObjectiveC(x: _ObjectiveCType,
// inout result: Self?) -> Bool
SWIFT_CC(swift)
- bool (*conditionallyBridgeFromObjectiveC)(
+ bool (*_protocolWitnessSignedPointer(conditionallyBridgeFromObjectiveC))(
HeapObject *sourceValue,
OpaqueValue *result,
SWIFT_CONTEXT const Metadata *self,
@@ -862,6 +865,7 @@
destFailureType, srcFailureType,
takeOnSuccess, mayDeferChecks);
#endif
+ SWIFT_FALLTHROUGH;
}
default:
return DynamicCastResult::Failure;
diff --git a/stdlib/public/runtime/KeyPaths.cpp b/stdlib/public/runtime/KeyPaths.cpp
index faa6292..4afed3e 100644
--- a/stdlib/public/runtime/KeyPaths.cpp
+++ b/stdlib/public/runtime/KeyPaths.cpp
@@ -119,9 +119,6 @@
YieldOnceTemporary::destroyAndDeallocateIn(buffer);
}
-// The resilient offset to the start of KeyPath's class-specific data.
-extern "C" size_t MANGLE_SYM(s7KeyPathCMo);
-
YieldOnceResult<const OpaqueValue*>
swift::swift_readAtKeyPath(YieldOnceBuffer *buffer,
const OpaqueValue *root, void *keyPath) {
@@ -129,17 +126,7 @@
// KeyPath is a native class, so we can just load its metadata directly
// even on ObjC-interop targets.
const Metadata *keyPathType = static_cast<HeapObject*>(keyPath)->metadata;
-
- // To find the generic arguments, we just have to find the class-specific
- // data section of the class; the generic arguments are always at the start
- // of that.
- //
- // We use the resilient access pattern because it's easy; since we're within
- // KeyPath's resilience domain, that's not really necessary, and it would
- // be totally valid to hard-code an offset.
- auto keyPathGenericArgs =
- reinterpret_cast<const Metadata * const *>(
- reinterpret_cast<const char*>(keyPathType) + MANGLE_SYM(s7KeyPathCMo));
+ auto keyPathGenericArgs = keyPathType->getGenericArgs();
const Metadata *valueTy = keyPathGenericArgs[1];
// Allocate the buffer.
diff --git a/stdlib/public/runtime/ReflectionMirror.mm b/stdlib/public/runtime/ReflectionMirror.mm
index 0206237..9a7b41e 100644
--- a/stdlib/public/runtime/ReflectionMirror.mm
+++ b/stdlib/public/runtime/ReflectionMirror.mm
@@ -328,8 +328,13 @@
void *fptr;
HeapObject *context;
};
+#if SWIFT_LIBRARY_EVOLUTION
SWIFT_RUNTIME_STDLIB_API SWIFT_CC(swift) swift_closure
MANGLE_SYM(s20_playgroundPrintHookySScSgvg)();
+#else
+SWIFT_RUNTIME_STDLIB_API swift_closure
+MANGLE_SYM(s20_playgroundPrintHookySScSgvp);
+#endif
static bool _shouldReportMissingReflectionMetadataWarnings() {
// Missing metadata warnings noise up playground sessions and aren't really
@@ -339,7 +344,11 @@
// Guesstimate whether we're in a playground by looking at the
// _playgroundPrintHook variable in the standard library, which is set during
// playground execution.
+ #if SWIFT_LIBRARY_EVOLUTION
auto hook = MANGLE_SYM(s20_playgroundPrintHookySScSgvg)();
+ #else
+ auto hook = MANGLE_SYM(s20_playgroundPrintHookySScSgvp);
+ #endif
if (hook.fptr) {
swift_release(hook.context);
return false;
diff --git a/test/AutoDiff/validation-test/forward_mode_array.swift b/test/AutoDiff/validation-test/forward_mode_array.swift
new file mode 100644
index 0000000..00b270d
--- /dev/null
+++ b/test/AutoDiff/validation-test/forward_mode_array.swift
@@ -0,0 +1,117 @@
+// RUN: %target-run-simple-swift(-Xfrontend -enable-experimental-forward-mode-differentiation)
+// REQUIRES: executable_test
+
+import StdlibUnittest
+import DifferentiationUnittest
+
+var ForwardModeTests = TestSuite("ForwardModeDifferentiation")
+
+//===----------------------------------------------------------------------===//
+// Array methods from ArrayDifferentiation.swift
+//===----------------------------------------------------------------------===//
+
+typealias FloatArrayTan = Array<Float>.TangentVector
+
+ForwardModeTests.test("Array.+") {
+ func sumFirstThreeConcatenating(_ a: [Float], _ b: [Float]) -> Float {
+ let c = a + b
+ return c[0] + c[1] + c[2]
+ }
+
+ expectEqual(3, differential(at: [0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([1, 1]), .init([1, 1])))
+ expectEqual(0, differential(at: [0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([0, 0]), .init([0, 1])))
+ expectEqual(1, differential(at: [0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([0, 1]), .init([0, 1])))
+ expectEqual(1, differential(at: [0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([1, 0]), .init([0, 1])))
+ expectEqual(1, differential(at: [0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([0, 0]), .init([1, 1])))
+ expectEqual(2, differential(at: [0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([1, 1]), .init([0, 1])))
+
+ expectEqual(
+ 3,
+ differential(at: [0, 0, 0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([1, 1, 1, 1]), .init([1, 1])))
+ expectEqual(
+ 3,
+ differential(at: [0, 0, 0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([1, 1, 1, 0]), .init([0, 0])))
+
+ expectEqual(
+ 3,
+ differential(at: [], [0, 0, 0, 0], in: sumFirstThreeConcatenating)(.init([]), .init([1, 1, 1, 1])))
+ expectEqual(
+ 0,
+ differential(at: [], [0, 0, 0, 0], in: sumFirstThreeConcatenating)(.init([]), .init([0, 0, 0, 1])))
+}
+
+ForwardModeTests.test("Array.init(repeating:count:)") {
+ @differentiable
+ func repeating(_ x: Float) -> [Float] {
+ Array(repeating: x, count: 10)
+ }
+ expectEqual(Float(10), derivative(at: .zero) { x in
+ repeating(x).differentiableReduce(0, {$0 + $1})
+ })
+ expectEqual(Float(20), differential(at: .zero, in: { x in
+ repeating(x).differentiableReduce(0, {$0 + $1})
+ })(2))
+}
+
+ForwardModeTests.test("Array.DifferentiableView.init") {
+ @differentiable
+ func constructView(_ x: [Float]) -> Array<Float>.DifferentiableView {
+ return Array<Float>.DifferentiableView(x)
+ }
+
+ let forward = differential(at: [5, 6, 7, 8], in: constructView)
+ expectEqual(
+ FloatArrayTan([1, 2, 3, 4]),
+ forward(FloatArrayTan([1, 2, 3, 4])))
+}
+
+ForwardModeTests.test("Array.DifferentiableView.base") {
+ @differentiable
+ func accessBase(_ x: Array<Float>.DifferentiableView) -> [Float] {
+ return x.base
+ }
+
+ let forward = differential(
+ at: Array<Float>.DifferentiableView([5, 6, 7, 8]),
+ in: accessBase)
+ expectEqual(
+ FloatArrayTan([1, 2, 3, 4]),
+ forward(FloatArrayTan([1, 2, 3, 4])))
+}
+
+ForwardModeTests.test("Array.differentiableMap") {
+ let x: [Float] = [1, 2, 3]
+ let tan = Array<Float>.TangentVector([1, 1, 1])
+
+ func multiplyMap(_ a: [Float]) -> [Float] {
+ return a.differentiableMap({ x in 3 * x })
+ }
+ expectEqual([3, 3, 3], differential(at: x, in: multiplyMap)(tan))
+
+ func squareMap(_ a: [Float]) -> [Float] {
+ return a.differentiableMap({ x in x * x })
+ }
+ expectEqual([2, 4, 6], differential(at: x, in: squareMap)(tan))
+}
+
+ForwardModeTests.test("Array.differentiableReduce") {
+ let x: [Float] = [1, 2, 3]
+ let tan = Array<Float>.TangentVector([1, 1, 1])
+
+ func sumReduce(_ a: [Float]) -> Float {
+ return a.differentiableReduce(0, { $0 + $1 })
+ }
+ expectEqual(1 + 1 + 1, differential(at: x, in: sumReduce)(tan))
+
+ func productReduce(_ a: [Float]) -> Float {
+ return a.differentiableReduce(1, { $0 * $1 })
+ }
+ expectEqual(x[1] * x[2] + x[0] * x[2] + x[0] * x[1], differential(at: x, in: productReduce)(tan))
+
+ func sumOfSquaresReduce(_ a: [Float]) -> Float {
+ return a.differentiableReduce(0, { $0 + $1 * $1 })
+ }
+ expectEqual(2 * x[0] + 2 * x[1] + 2 * x[2], differential(at: x, in: sumOfSquaresReduce)(tan))
+}
+
+runAllTests()
diff --git a/test/AutoDiff/validation-test/forward_mode_simd.swift b/test/AutoDiff/validation-test/forward_mode_simd.swift
new file mode 100644
index 0000000..03e600b
--- /dev/null
+++ b/test/AutoDiff/validation-test/forward_mode_simd.swift
@@ -0,0 +1,249 @@
+// RUN: %target-run-simple-swift(-Xfrontend -enable-experimental-forward-mode-differentiation)
+// REQUIRES: executable_test
+
+import StdlibUnittest
+import DifferentiationUnittest
+
+var ForwardModeTests = TestSuite("ForwardModeDifferentiation")
+
+//===----------------------------------------------------------------------===//
+// SIMD methods from SIMDDifferentiation.swift.gyb
+// Tests replicate reverse mode tests from test/AutoDiff/stdlib/simd.swift
+//===----------------------------------------------------------------------===//
+
+ForwardModeTests.test("init(repeating:)") {
+ func foo1(x: Float) -> SIMD4<Float> {
+ return SIMD4<Float>(repeating: 2 * x)
+ }
+ let (val1, df1) = valueWithDifferential(at: 5, in: foo1)
+ expectEqual(SIMD4<Float>(10, 10, 10, 10), val1)
+ expectEqual(SIMD4<Float>(6, 6, 6, 6), df1(3))
+}
+
+ForwardModeTests.test("Identity") {
+ let a = SIMD4<Float>(1, 2, 3, 4)
+ let g = SIMD4<Float>(1, 1, 1, 1)
+
+ func foo1(x: SIMD4<Float>) -> SIMD4<Float> {
+ return x
+ }
+ let (val1, df1) = valueWithDifferential(at: a, in: foo1)
+ expectEqual(a, val1)
+ expectEqual(g, df1(.init(g)))
+}
+
+ForwardModeTests.test("Negate") {
+ let a = SIMD4<Float>(1, 2, 3, 4)
+ let g = SIMD4<Float>(1, 1, 1, 1)
+
+ func foo1(x: SIMD4<Float>) -> SIMD4<Float> {
+ return -x
+ }
+ let (val1, df1) = valueWithDifferential(at: a, in: foo1)
+ expectEqual(-a, val1)
+ expectEqual(-g, df1(.init(g)))
+}
+
+ForwardModeTests.test("subscript") {
+ let a = SIMD4<Float>(1, 2, 3, 4)
+
+ func foo1(x: SIMD4<Float>) -> Float {
+ return x[3]
+ }
+
+ let (val1, df1) = valueWithDifferential(at: a, in: foo1)
+ expectEqual(4, val1)
+ expectEqual(4, df1(a))
+}
+
+ForwardModeTests.test("Addition") {
+ let a = SIMD4<Float>(1, 2, 3, 4)
+ let g = SIMD4<Float>(1, 1, 1, 1)
+
+ // SIMD + SIMD
+ func foo1(x: SIMD4<Float>, y: SIMD4<Float>) -> SIMD4<Float> {
+ return x + y
+ }
+ let (val1, df1) = valueWithDifferential(at: a, a, in: foo1)
+ expectEqual(SIMD4<Float>(2, 4, 6, 8), val1)
+ expectEqual(a + g, df1(a, g))
+
+ // SIMD + Scalar
+ func foo2(x: SIMD4<Float>, y: Float) -> SIMD4<Float> {
+ return x + y
+ }
+ let (val2, df2) = valueWithDifferential(at: a, 5, in: foo2)
+ expectEqual(SIMD4<Float>(6, 7, 8, 9), val2)
+ expectEqual(g + 1, df2(g, 1))
+
+ // Scalar + SIMD
+ func foo3(x: SIMD4<Float>, y: Float) -> SIMD4<Float> {
+ return y + x
+ }
+ let (val3, df3) = valueWithDifferential(at: a, 5, in: foo3)
+ expectEqual(SIMD4<Float>(6, 7, 8, 9), val3)
+ expectEqual(2 + g, df3(g, 2))
+}
+
+ForwardModeTests.test("Subtraction") {
+ let a = SIMD4<Float>(1, 2, 3, 4)
+ let g = SIMD4<Float>(1, 1, 1, 1)
+
+ // SIMD - SIMD
+ func foo1(x: SIMD4<Float>, y: SIMD4<Float>) -> SIMD4<Float> {
+ return x - y
+ }
+ let (val1, df1) = valueWithDifferential(at: a, a, in: foo1)
+ expectEqual(SIMD4<Float>(0, 0, 0, 0), val1)
+ expectEqual(g - a, df1(g, a))
+
+ // SIMD - Scalar
+ func foo2(x: SIMD4<Float>, y: Float) -> SIMD4<Float> {
+ return x - y
+ }
+ let (val2, df2) = valueWithDifferential(at: a, 5, in: foo2)
+ expectEqual(SIMD4<Float>(-4, -3, -2, -1), val2)
+ expectEqual(g - 1, df2(g, 1))
+
+ // Scalar - SIMD
+ func foo3(x: SIMD4<Float>, y: Float) -> SIMD4<Float> {
+ return y - x
+ }
+ let (val3, df3) = valueWithDifferential(at: a, 5, in: foo3)
+ expectEqual(SIMD4<Float>(4, 3, 2, 1), val3)
+ expectEqual(2 - g, df3(g, 2))
+}
+
+ForwardModeTests.test("Multiplication") {
+ let a = SIMD4<Float>(1, 2, 3, 4)
+ let a2 = SIMD4<Float>(4, 3, 2, 1)
+ let g = SIMD4<Float>(1, 1, 1, 1)
+ let g2 = SIMD4<Float>(0, 2, 1, 3)
+
+ // SIMD * SIMD
+ func foo1(x: SIMD4<Float>, y: SIMD4<Float>) -> SIMD4<Float> {
+ return x * y
+ }
+ let (val1, df1) = valueWithDifferential(at: a, a2, in: foo1)
+ expectEqual(a * a2, val1)
+ expectEqual(a * g2 + g * a2, df1(g, g2))
+
+ // SIMD * Scalar
+ func foo2(x: SIMD4<Float>, y: Float) -> SIMD4<Float> {
+ return x * y
+ }
+ let (val2, df2) = valueWithDifferential(at: a, 5, in: foo2)
+ expectEqual(a * 5, val2)
+ expectEqual(a * 2 + g * 5, df2(g, 2))
+
+ // Scalar * SIMD
+ func foo3(x: SIMD4<Float>, y: Float) -> SIMD4<Float> {
+ return y * x
+ }
+ let (val3, df3) = valueWithDifferential(at: a, 5, in: foo3)
+ expectEqual(a * 5, val3)
+ expectEqual(a * 3 + g * 5, df3(g, 3))
+}
+
+ForwardModeTests.test("Division") {
+ let a = SIMD4<Float>(1, 2, 3, 4)
+ let g = SIMD4<Float>(1, 1, 1, 1)
+
+ // SIMD / SIMD
+ func foo1(x: SIMD4<Float>, y: SIMD4<Float>) -> SIMD4<Float> {
+ return x / y
+ }
+ let (val1, df1) = valueWithDifferential(at: a, a, in: foo1)
+ expectEqual(a / a, val1)
+ expectEqual((g * a - a * g) / (a * a)/* == 0 */, df1(g, g))
+
+ // SIMD / Scalar
+ func foo2(x: SIMD4<Float>, y: Float) -> SIMD4<Float> {
+ return x / y
+ }
+ let (val2, df2) = valueWithDifferential(at: a, 5, in: foo2)
+ expectEqual(a / 5, val2)
+ expectEqual((g * 5 - a * 2) / (5 * 5), df2(g, 2))
+
+ // Scalar / SIMD
+ func foo3(x: Float, y: SIMD4<Float>) -> SIMD4<Float> {
+ return x / y
+ }
+ let (val3, df3) = valueWithDifferential(at: 5, a, in: foo3)
+ expectEqual(5 / a, val3)
+ expectEqual((3 * a - 5 * g) / (a * a), df3(3, g))
+}
+
+ForwardModeTests.test("Generics") {
+ let a = SIMD3<Double>(1, 2, 3)
+ let g = SIMD3<Double>(1, 1, 1)
+
+ // FIXME(SR-13210): Fix forward-mode SIL verification error.
+ /*
+ func testInit<Scalar, SIMDType: SIMD>(x: Scalar) -> SIMDType
+ where SIMDType.Scalar == Scalar,
+ SIMDType : Differentiable,
+ Scalar : BinaryFloatingPoint & Differentiable,
+ SIMDType.TangentVector == SIMDType,
+ Scalar.TangentVector == Scalar {
+ return SIMDType.init(repeating: x)
+ }
+ func simd3Init(x: Double) -> SIMD3<Double> { testInit(x: x) }
+ let (val1, df1) = valueWithDifferential(at: 10, in: simd3Init)
+ expectEqual(SIMD3<Double>(10, 10, 10), val1)
+ expectEqual(SIMD3<Double>(5, 5, 5), df1(5))
+ */
+
+ // SIMDType + SIMDType
+ func testAddition<Scalar, SIMDType: SIMD>(lhs: SIMDType, rhs: SIMDType)
+ -> SIMDType
+ where SIMDType.Scalar == Scalar,
+ SIMDType : Differentiable,
+ SIMDType.TangentVector : SIMD,
+ Scalar : BinaryFloatingPoint,
+ SIMDType.TangentVector.Scalar : BinaryFloatingPoint {
+ return lhs + rhs
+ }
+ func simd3Add(lhs: SIMD3<Double>, rhs: SIMD3<Double>) -> SIMD3<Double> {
+ return testAddition(lhs: lhs, rhs: rhs)
+ }
+ let (val2, df2) = valueWithDifferential(at: a, a, in: simd3Add)
+ expectEqual(SIMD3<Double>(2, 4, 6), val2)
+ expectEqual(g + a, df2(g, a))
+
+ // Scalar - SIMDType
+ func testSubtraction<Scalar, SIMDType: SIMD>(lhs: Scalar, rhs: SIMDType)
+ -> SIMDType
+ where SIMDType.Scalar == Scalar,
+ SIMDType : Differentiable,
+ Scalar : BinaryFloatingPoint & Differentiable,
+ SIMDType.TangentVector == SIMDType,
+ Scalar.TangentVector == Scalar {
+ return lhs - rhs
+ }
+ func simd3Subtract(lhs: Double, rhs: SIMD3<Double>) -> SIMD3<Double> {
+ return testSubtraction(lhs: lhs, rhs: rhs)
+ }
+ let (val3, df3) = valueWithDifferential(at: 5, a, in: simd3Subtract)
+ expectEqual(SIMD3<Double>(4, 3, 2), val3)
+ expectEqual(2 - g, df3(2, g))
+
+ // SIMDType * Scalar
+ func testMultipication<Scalar, SIMDType: SIMD>(lhs: SIMDType, rhs: Scalar)
+ -> SIMDType
+ where SIMDType.Scalar == Scalar,
+ SIMDType : Differentiable,
+ Scalar : BinaryFloatingPoint & Differentiable,
+ SIMDType.TangentVector == SIMDType,
+ Scalar.TangentVector == Scalar {
+ return lhs * rhs
+ }
+ func simd3Multiply(lhs: SIMD3<Double>, rhs: Double) -> SIMD3<Double> {
+ return testMultipication(lhs: lhs, rhs: rhs)
+ }
+ let (val4, df4) = valueWithDifferential(at: a, 5, in: simd3Multiply)
+ expectEqual(SIMD3<Double>(5, 10, 15), val4)
+ expectEqual(a * 3 + g * 5 , df4(g, 3))
+}
+
+runAllTests()
diff --git a/test/AutoDiff/validation-test/forward_mode.swift b/test/AutoDiff/validation-test/forward_mode_simple.swift
similarity index 77%
rename from test/AutoDiff/validation-test/forward_mode.swift
rename to test/AutoDiff/validation-test/forward_mode_simple.swift
index 906d9de..57c85eb 100644
--- a/test/AutoDiff/validation-test/forward_mode.swift
+++ b/test/AutoDiff/validation-test/forward_mode_simple.swift
@@ -1389,352 +1389,4 @@
expectEqual(1.0, derivative(at: 2, in: applyNonactiveArgumentActiveIndirectResult))
}
-//===----------------------------------------------------------------------===//
-// Array methods from ArrayDifferentiation.swift
-//===----------------------------------------------------------------------===//
-
-typealias FloatArrayTan = Array<Float>.TangentVector
-
-ForwardModeTests.test("Array.+") {
- func sumFirstThreeConcatenating(_ a: [Float], _ b: [Float]) -> Float {
- let c = a + b
- return c[0] + c[1] + c[2]
- }
-
- expectEqual(3, differential(at: [0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([1, 1]), .init([1, 1])))
- expectEqual(0, differential(at: [0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([0, 0]), .init([0, 1])))
- expectEqual(1, differential(at: [0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([0, 1]), .init([0, 1])))
- expectEqual(1, differential(at: [0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([1, 0]), .init([0, 1])))
- expectEqual(1, differential(at: [0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([0, 0]), .init([1, 1])))
- expectEqual(2, differential(at: [0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([1, 1]), .init([0, 1])))
-
- expectEqual(
- 3,
- differential(at: [0, 0, 0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([1, 1, 1, 1]), .init([1, 1])))
- expectEqual(
- 3,
- differential(at: [0, 0, 0, 0], [0, 0], in: sumFirstThreeConcatenating)(.init([1, 1, 1, 0]), .init([0, 0])))
-
- expectEqual(
- 3,
- differential(at: [], [0, 0, 0, 0], in: sumFirstThreeConcatenating)(.init([]), .init([1, 1, 1, 1])))
- expectEqual(
- 0,
- differential(at: [], [0, 0, 0, 0], in: sumFirstThreeConcatenating)(.init([]), .init([0, 0, 0, 1])))
-}
-
-ForwardModeTests.test("Array.init(repeating:count:)") {
- @differentiable
- func repeating(_ x: Float) -> [Float] {
- Array(repeating: x, count: 10)
- }
- expectEqual(Float(10), derivative(at: .zero) { x in
- repeating(x).differentiableReduce(0, {$0 + $1})
- })
- expectEqual(Float(20), differential(at: .zero, in: { x in
- repeating(x).differentiableReduce(0, {$0 + $1})
- })(2))
-}
-
-ForwardModeTests.test("Array.DifferentiableView.init") {
- @differentiable
- func constructView(_ x: [Float]) -> Array<Float>.DifferentiableView {
- return Array<Float>.DifferentiableView(x)
- }
-
- let forward = differential(at: [5, 6, 7, 8], in: constructView)
- expectEqual(
- FloatArrayTan([1, 2, 3, 4]),
- forward(FloatArrayTan([1, 2, 3, 4])))
-}
-
-ForwardModeTests.test("Array.DifferentiableView.base") {
- @differentiable
- func accessBase(_ x: Array<Float>.DifferentiableView) -> [Float] {
- return x.base
- }
-
- let forward = differential(
- at: Array<Float>.DifferentiableView([5, 6, 7, 8]),
- in: accessBase)
- expectEqual(
- FloatArrayTan([1, 2, 3, 4]),
- forward(FloatArrayTan([1, 2, 3, 4])))
-}
-
-ForwardModeTests.test("Array.differentiableMap") {
- let x: [Float] = [1, 2, 3]
- let tan = Array<Float>.TangentVector([1, 1, 1])
-
- func multiplyMap(_ a: [Float]) -> [Float] {
- return a.differentiableMap({ x in 3 * x })
- }
- expectEqual([3, 3, 3], differential(at: x, in: multiplyMap)(tan))
-
- func squareMap(_ a: [Float]) -> [Float] {
- return a.differentiableMap({ x in x * x })
- }
- expectEqual([2, 4, 6], differential(at: x, in: squareMap)(tan))
-}
-
-ForwardModeTests.test("Array.differentiableReduce") {
- let x: [Float] = [1, 2, 3]
- let tan = Array<Float>.TangentVector([1, 1, 1])
-
- func sumReduce(_ a: [Float]) -> Float {
- return a.differentiableReduce(0, { $0 + $1 })
- }
- expectEqual(1 + 1 + 1, differential(at: x, in: sumReduce)(tan))
-
- func productReduce(_ a: [Float]) -> Float {
- return a.differentiableReduce(1, { $0 * $1 })
- }
- expectEqual(x[1] * x[2] + x[0] * x[2] + x[0] * x[1], differential(at: x, in: productReduce)(tan))
-
- func sumOfSquaresReduce(_ a: [Float]) -> Float {
- return a.differentiableReduce(0, { $0 + $1 * $1 })
- }
- expectEqual(2 * x[0] + 2 * x[1] + 2 * x[2], differential(at: x, in: sumOfSquaresReduce)(tan))
-}
-
-//===----------------------------------------------------------------------===//
-// SIMD methods from SIMDDifferentiation.swift.gyb
-// Tests replicate reverse mode tests from test/AutoDiff/stdlib/simd.swift
-//===----------------------------------------------------------------------===//
-
-ForwardModeTests.test("init(repeating:)") {
- func foo1(x: Float) -> SIMD4<Float> {
- return SIMD4<Float>(repeating: 2 * x)
- }
- let (val1, df1) = valueWithDifferential(at: 5, in: foo1)
- expectEqual(SIMD4<Float>(10, 10, 10, 10), val1)
- expectEqual(SIMD4<Float>(6, 6, 6, 6), df1(3))
-}
-
-ForwardModeTests.test("Identity") {
- let a = SIMD4<Float>(1, 2, 3, 4)
- let g = SIMD4<Float>(1, 1, 1, 1)
-
- func foo1(x: SIMD4<Float>) -> SIMD4<Float> {
- return x
- }
- let (val1, df1) = valueWithDifferential(at: a, in: foo1)
- expectEqual(a, val1)
- expectEqual(g, df1(.init(g)))
-}
-
-ForwardModeTests.test("Negate") {
- let a = SIMD4<Float>(1, 2, 3, 4)
- let g = SIMD4<Float>(1, 1, 1, 1)
-
- func foo1(x: SIMD4<Float>) -> SIMD4<Float> {
- return -x
- }
- let (val1, df1) = valueWithDifferential(at: a, in: foo1)
- expectEqual(-a, val1)
- expectEqual(-g, df1(.init(g)))
-}
-
-ForwardModeTests.test("subscript") {
- let a = SIMD4<Float>(1, 2, 3, 4)
-
- func foo1(x: SIMD4<Float>) -> Float {
- return x[3]
- }
-
- let (val1, df1) = valueWithDifferential(at: a, in: foo1)
- expectEqual(4, val1)
- expectEqual(4, df1(a))
-}
-
-ForwardModeTests.test("Addition") {
- let a = SIMD4<Float>(1, 2, 3, 4)
- let g = SIMD4<Float>(1, 1, 1, 1)
-
- // SIMD + SIMD
- func foo1(x: SIMD4<Float>, y: SIMD4<Float>) -> SIMD4<Float> {
- return x + y
- }
- let (val1, df1) = valueWithDifferential(at: a, a, in: foo1)
- expectEqual(SIMD4<Float>(2, 4, 6, 8), val1)
- expectEqual(a + g, df1(a, g))
-
- // SIMD + Scalar
- func foo2(x: SIMD4<Float>, y: Float) -> SIMD4<Float> {
- return x + y
- }
- let (val2, df2) = valueWithDifferential(at: a, 5, in: foo2)
- expectEqual(SIMD4<Float>(6, 7, 8, 9), val2)
- expectEqual(g + 1, df2(g, 1))
-
- // Scalar + SIMD
- func foo3(x: SIMD4<Float>, y: Float) -> SIMD4<Float> {
- return y + x
- }
- let (val3, df3) = valueWithDifferential(at: a, 5, in: foo3)
- expectEqual(SIMD4<Float>(6, 7, 8, 9), val3)
- expectEqual(2 + g, df3(g, 2))
-}
-
-ForwardModeTests.test("Subtraction") {
- let a = SIMD4<Float>(1, 2, 3, 4)
- let g = SIMD4<Float>(1, 1, 1, 1)
-
- // SIMD - SIMD
- func foo1(x: SIMD4<Float>, y: SIMD4<Float>) -> SIMD4<Float> {
- return x - y
- }
- let (val1, df1) = valueWithDifferential(at: a, a, in: foo1)
- expectEqual(SIMD4<Float>(0, 0, 0, 0), val1)
- expectEqual(g - a, df1(g, a))
-
- // SIMD - Scalar
- func foo2(x: SIMD4<Float>, y: Float) -> SIMD4<Float> {
- return x - y
- }
- let (val2, df2) = valueWithDifferential(at: a, 5, in: foo2)
- expectEqual(SIMD4<Float>(-4, -3, -2, -1), val2)
- expectEqual(g - 1, df2(g, 1))
-
- // Scalar - SIMD
- func foo3(x: SIMD4<Float>, y: Float) -> SIMD4<Float> {
- return y - x
- }
- let (val3, df3) = valueWithDifferential(at: a, 5, in: foo3)
- expectEqual(SIMD4<Float>(4, 3, 2, 1), val3)
- expectEqual(2 - g, df3(g, 2))
-}
-
-ForwardModeTests.test("Multiplication") {
- let a = SIMD4<Float>(1, 2, 3, 4)
- let a2 = SIMD4<Float>(4, 3, 2, 1)
- let g = SIMD4<Float>(1, 1, 1, 1)
- let g2 = SIMD4<Float>(0, 2, 1, 3)
-
- // SIMD * SIMD
- func foo1(x: SIMD4<Float>, y: SIMD4<Float>) -> SIMD4<Float> {
- return x * y
- }
- let (val1, df1) = valueWithDifferential(at: a, a2, in: foo1)
- expectEqual(a * a2, val1)
- expectEqual(a * g2 + g * a2, df1(g, g2))
-
- // SIMD * Scalar
- func foo2(x: SIMD4<Float>, y: Float) -> SIMD4<Float> {
- return x * y
- }
- let (val2, df2) = valueWithDifferential(at: a, 5, in: foo2)
- expectEqual(a * 5, val2)
- expectEqual(a * 2 + g * 5, df2(g, 2))
-
- // Scalar * SIMD
- func foo3(x: SIMD4<Float>, y: Float) -> SIMD4<Float> {
- return y * x
- }
- let (val3, df3) = valueWithDifferential(at: a, 5, in: foo3)
- expectEqual(a * 5, val3)
- expectEqual(a * 3 + g * 5, df3(g, 3))
-}
-
-ForwardModeTests.test("Division") {
- let a = SIMD4<Float>(1, 2, 3, 4)
- let g = SIMD4<Float>(1, 1, 1, 1)
-
- // SIMD / SIMD
- func foo1(x: SIMD4<Float>, y: SIMD4<Float>) -> SIMD4<Float> {
- return x / y
- }
- let (val1, df1) = valueWithDifferential(at: a, a, in: foo1)
- expectEqual(a / a, val1)
- expectEqual((g * a - a * g) / (a * a)/* == 0 */, df1(g, g))
-
- // SIMD / Scalar
- func foo2(x: SIMD4<Float>, y: Float) -> SIMD4<Float> {
- return x / y
- }
- let (val2, df2) = valueWithDifferential(at: a, 5, in: foo2)
- expectEqual(a / 5, val2)
- expectEqual((g * 5 - a * 2) / (5 * 5), df2(g, 2))
-
- // Scalar / SIMD
- func foo3(x: Float, y: SIMD4<Float>) -> SIMD4<Float> {
- return x / y
- }
- let (val3, df3) = valueWithDifferential(at: 5, a, in: foo3)
- expectEqual(5 / a, val3)
- expectEqual((3 * a - 5 * g) / (a * a), df3(3, g))
-}
-
-ForwardModeTests.test("Generics") {
- let a = SIMD3<Double>(1, 2, 3)
- let g = SIMD3<Double>(1, 1, 1)
-
- // FIXME(SR-13210): Fix forward-mode SIL verification error.
- /*
- func testInit<Scalar, SIMDType: SIMD>(x: Scalar) -> SIMDType
- where SIMDType.Scalar == Scalar,
- SIMDType : Differentiable,
- Scalar : BinaryFloatingPoint & Differentiable,
- SIMDType.TangentVector == SIMDType,
- Scalar.TangentVector == Scalar {
- return SIMDType.init(repeating: x)
- }
- func simd3Init(x: Double) -> SIMD3<Double> { testInit(x: x) }
- let (val1, df1) = valueWithDifferential(at: 10, in: simd3Init)
- expectEqual(SIMD3<Double>(10, 10, 10), val1)
- expectEqual(SIMD3<Double>(5, 5, 5), df1(5))
- */
-
- // SIMDType + SIMDType
- func testAddition<Scalar, SIMDType: SIMD>(lhs: SIMDType, rhs: SIMDType)
- -> SIMDType
- where SIMDType.Scalar == Scalar,
- SIMDType : Differentiable,
- SIMDType.TangentVector : SIMD,
- Scalar : BinaryFloatingPoint,
- SIMDType.TangentVector.Scalar : BinaryFloatingPoint {
- return lhs + rhs
- }
- func simd3Add(lhs: SIMD3<Double>, rhs: SIMD3<Double>) -> SIMD3<Double> {
- return testAddition(lhs: lhs, rhs: rhs)
- }
- let (val2, df2) = valueWithDifferential(at: a, a, in: simd3Add)
- expectEqual(SIMD3<Double>(2, 4, 6), val2)
- expectEqual(g + a, df2(g, a))
-
- // Scalar - SIMDType
- func testSubtraction<Scalar, SIMDType: SIMD>(lhs: Scalar, rhs: SIMDType)
- -> SIMDType
- where SIMDType.Scalar == Scalar,
- SIMDType : Differentiable,
- Scalar : BinaryFloatingPoint & Differentiable,
- SIMDType.TangentVector == SIMDType,
- Scalar.TangentVector == Scalar {
- return lhs - rhs
- }
- func simd3Subtract(lhs: Double, rhs: SIMD3<Double>) -> SIMD3<Double> {
- return testSubtraction(lhs: lhs, rhs: rhs)
- }
- let (val3, df3) = valueWithDifferential(at: 5, a, in: simd3Subtract)
- expectEqual(SIMD3<Double>(4, 3, 2), val3)
- expectEqual(2 - g, df3(2, g))
-
- // SIMDType * Scalar
- func testMultipication<Scalar, SIMDType: SIMD>(lhs: SIMDType, rhs: Scalar)
- -> SIMDType
- where SIMDType.Scalar == Scalar,
- SIMDType : Differentiable,
- Scalar : BinaryFloatingPoint & Differentiable,
- SIMDType.TangentVector == SIMDType,
- Scalar.TangentVector == Scalar {
- return lhs * rhs
- }
- func simd3Multiply(lhs: SIMD3<Double>, rhs: Double) -> SIMD3<Double> {
- return testMultipication(lhs: lhs, rhs: rhs)
- }
- let (val4, df4) = valueWithDifferential(at: a, 5, in: simd3Multiply)
- expectEqual(SIMD3<Double>(5, 10, 15), val4)
- expectEqual(a * 3 + g * 5 , df4(g, 3))
-}
-
runAllTests()
diff --git a/test/AutoDiff/validation-test/optional-property.swift b/test/AutoDiff/validation-test/optional-property.swift
index 7a8b150..000433f 100644
--- a/test/AutoDiff/validation-test/optional-property.swift
+++ b/test/AutoDiff/validation-test/optional-property.swift
@@ -1,6 +1,7 @@
// RUN: %target-run-simple-swift
// RUN: %target-swift-emit-sil -Xllvm -debug-only=differentiation -o /dev/null 2>&1 %s | %FileCheck %s
// REQUIRES: executable_test
+// REQUIRES: asserts
// Test differentiation of `Optional` properties.
diff --git a/test/Constraints/rdar68155466.swift b/test/Constraints/rdar68155466.swift
new file mode 100644
index 0000000..f8c4e17
--- /dev/null
+++ b/test/Constraints/rdar68155466.swift
@@ -0,0 +1,28 @@
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify %s
+// REQUIRES: objc_interop
+
+import Foundation
+
+@objc class A : NSObject {
+ func uniqueID() -> Int {
+ 42
+ }
+}
+
+struct Loop< // expected-note {{required by generic struct 'Loop' where 'ID' = '() -> Int'}}
+ Data : RandomAccessCollection,
+ ID : Hashable,
+ Content
+> {
+ public init(
+ _ data: Data,
+ id: KeyPath<Data.Element, ID>,
+ content: @escaping (Data.Element) -> Content) {}
+}
+
+func data() -> [A] {
+ return []
+}
+
+_ = Loop(data(), id: \.uniqueID) { $0 } // expected-error {{key path cannot refer to instance method 'uniqueID()'}}
+// expected-error@-1 {{type '() -> Int' cannot conform to 'Hashable'; only concrete types such as structs, enums and classes can conform to protocols}}
diff --git a/test/Driver/verify-module-interface.swift b/test/Driver/verify-module-interface.swift
new file mode 100644
index 0000000..6f277fa
--- /dev/null
+++ b/test/Driver/verify-module-interface.swift
@@ -0,0 +1,12 @@
+// RUN: %empty-directory(%t)
+// RUN: touch %t/file-01.swift %t/file-02.swift %t/file-03.swift
+
+// RUN: %swiftc_driver -driver-print-jobs -driver-skip-execution -j 3 -emit-module -module-name foo -emit-module-interface %t/file-01.swift %t/file-02.swift %t/file-03.swift -verify-emitted-module-interface -enable-library-evolution >%t/evolution.txt
+
+// RUN: %swiftc_driver -driver-print-jobs -driver-skip-execution -j 3 -emit-module -module-name foo -emit-module-interface %t/file-01.swift %t/file-02.swift %t/file-03.swift -verify-emitted-module-interface >%t/no-evolution.txt
+
+// RUN: %FileCheck %s --check-prefix=CHECK_EVOLUTION <%t/evolution.txt
+// RUN: %FileCheck %s --check-prefix=CHECK_NO_EVOLUTION <%t/no-evolution.txt
+
+// CHECK_EVOLUTION: -typecheck-module-from-interface
+// CHECK_NO_EVOLUTION-NOT: -typecheck-module-from-interface
diff --git a/test/IDE/complete_ambiguous.swift b/test/IDE/complete_ambiguous.swift
new file mode 100644
index 0000000..6931abc
--- /dev/null
+++ b/test/IDE/complete_ambiguous.swift
@@ -0,0 +1,137 @@
+// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=SIMPLE | %FileCheck %s --check-prefix=SIMPLE
+// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=SIMPLE_EXTRAARG | %FileCheck %s --check-prefix=SIMPLE
+// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=SIMPLE_MEMBERS | %FileCheck %s --check-prefix=SIMPLE
+// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=RELATED | %FileCheck %s --check-prefix=RELATED
+// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=RELATED_EXTRAARG | %FileCheck %s --check-prefix=RELATED
+// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=RELATED_INERROREXPR | %FileCheck %s --check-prefix=RELATED
+// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERIC | %FileCheck %s --check-prefix=GENERIC
+// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERIC_MISSINGARG | %FileCheck %s --check-prefix=NORESULTS
+// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLOSURE_MISSINGARG | %FileCheck %s --check-prefix=POINT_MEMBER
+// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLOSURE_NORETURN | %FileCheck %s --check-prefix=POINT_MEMBER
+// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLOSURE_FUNCBUILDER | %FileCheck %s --check-prefix=POINT_MEMBER
+
+struct A {
+ func doAThings() -> A { return self }
+}
+
+struct B {
+ func doBThings() {}
+}
+
+func overloadedReturn() -> A { return A() }
+func overloadedReturn() -> B { return B() }
+
+overloadedReturn().#^SIMPLE^#
+overloadedReturn(1).#^SIMPLE_EXTRAARG^#
+
+struct HasMembers {
+ func overloadedReturn() -> A { return A() }
+ func overloadedReturn() -> B { return B() }
+}
+
+HasMembers().overloadedReturn().#^SIMPLE_MEMBERS^#
+
+// SIMPLE: Begin completions, 4 items
+// SIMPLE-DAG: Keyword[self]/CurrNominal: self[#A#]{{; name=.+$}}
+// SIMPLE-DAG: Decl[InstanceMethod]/CurrNominal: doAThings()[#A#]{{; name=.+$}}
+// SIMPLE-DAG: Keyword[self]/CurrNominal: self[#B#]{{; name=.+$}}
+// SIMPLE-DAG: Decl[InstanceMethod]/CurrNominal: doBThings()[#Void#]{{; name=.+$}}
+// SIMPLE: End completions
+
+let x: A = overloadedReturn().#^RELATED^#
+let x: A = overloadedReturn(1).#^RELATED_EXTRAARG^#
+
+// RELATED: Begin completions, 4 items
+// RELATED-DAG: Keyword[self]/CurrNominal: self[#A#]{{; name=.+$}}
+// RELATED-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: doAThings()[#A#]{{; name=.+$}}
+// RELATED-DAG: Keyword[self]/CurrNominal: self[#B#]{{; name=.+$}}
+// RELATED-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: doBThings()[#Void#]{{; name=.+$}}
+// RELATED: End completions
+
+func takesA(_ callback: () -> A) -> B {}
+func takesB(_ item: B) {}
+
+takesB((takesA { return overloadedReturn().#^RELATED_INERROREXPR^# }).)
+
+protocol C {
+ associatedtype Element
+ func getCElem() -> Element
+}
+
+protocol D {
+ associatedtype Item
+ func getDElem() -> Item
+}
+
+struct CDStruct: C, D {
+ func getDElem() -> A { return A() }
+ func getCElem() -> B { return B() }
+}
+
+func genericReturn<T:C, U>(_ x: T) -> U where U == T.Element {
+ return x.getCElem()
+}
+func genericReturn<T:D, U>(_ x: T) -> U where U == T.Item {
+ return x.getDElem()
+}
+
+genericReturn(CDStruct()).#^GENERIC^#
+
+// GENERIC: Begin completions, 4 items
+// GENERIC-DAG: Keyword[self]/CurrNominal: self[#B#]{{; name=.+$}}
+// GENERIC-DAG: Decl[InstanceMethod]/CurrNominal: doBThings()[#Void#]{{; name=.+$}}
+// GENERIC-DAG: Keyword[self]/CurrNominal: self[#A#]{{; name=.+$}}
+// GENERIC-DAG: Decl[InstanceMethod]/CurrNominal: doAThings()[#A#]{{; name=.+$}}
+// GENERIC: End completions
+
+genericReturn().#^GENERIC_MISSINGARG^#
+
+// NORESULTS-NOT: Begin completions
+
+struct Point {
+ let x: Int
+ let y: Int
+ var magSquared: Int { return x*y }
+
+ init(_ x: Int, _ y: Int) {
+ self.x = x
+ self.y = y
+ }
+}
+
+// POINT_MEMBER: Begin completions, 4 items
+// POINT_MEMBER-DAG: Keyword[self]/CurrNominal: self[#Point#]; name=self
+// POINT_MEMBER-DAG: Decl[InstanceVar]/CurrNominal: x[#Int#]; name=x
+// POINT_MEMBER-DAG: Decl[InstanceVar]/CurrNominal: y[#Int#]; name=y
+// POINT_MEMBER-DAG: Decl[InstanceVar]/CurrNominal: magSquared[#Int#]; name=magSquared
+// POINT_MEMBER: End completions
+
+let _ = [Point(1, 4), Point(20, 2), Point(9, -4)]
+ .filter { $0.magSquared > 4 }
+ .min {
+ $0.#^CLOSURE_MISSINGARG^#
+ }
+
+protocol SomeProto {}
+func testing<T: Collection, U: SomeProto>(_ arg1: T, arg2: (T.Element) -> U) {}
+_ = testing([Point(4, 89)]) { arg in
+ arg.#^CLOSURE_NORETURN^#
+}
+
+struct Thing {
+ init(_ block: (Point) -> Void) {}
+}
+@_functionBuilder
+struct ThingBuilder {
+ static func buildBlock(_ x: Thing...) -> [Thing] { x }
+}
+func CreateThings(@ThingBuilder makeThings: () -> [Thing]) {}
+
+// FIXME: only works if the first call to Thing is passed a single expression closure
+CreateThings {
+ Thing { point in
+ point.#^CLOSURE_FUNCBUILDER^#
+ }
+ Thing { _ in }
+}
+
diff --git a/test/IDE/complete_decl_attribute.swift b/test/IDE/complete_decl_attribute.swift
index d03834a..72df159 100644
--- a/test/IDE/complete_decl_attribute.swift
+++ b/test/IDE/complete_decl_attribute.swift
@@ -39,6 +39,7 @@
// AVAILABILITY1-NEXT: Keyword/None: macOSApplicationExtension[#Platform#]; name=macOSApplicationExtension{{$}}
// AVAILABILITY1-NEXT: Keyword/None: macCatalyst[#Platform#]; name=macCatalyst
// AVAILABILITY1-NEXT: Keyword/None: macCatalystApplicationExtension[#Platform#]; name=macCatalystApplicationExtension
+// AVAILABILITY1-NEXT: Keyword/None: OpenBSD[#Platform#]; name=OpenBSD{{$}}
// AVAILABILITY1-NEXT: End completions
@available(*, #^AVAILABILITY2^#)
diff --git a/test/IDE/complete_enum_elements.swift b/test/IDE/complete_enum_elements.swift
index 48d8b01d..a087c24 100644
--- a/test/IDE/complete_enum_elements.swift
+++ b/test/IDE/complete_enum_elements.swift
@@ -57,7 +57,7 @@
// RUN: %FileCheck %s -check-prefix=QUX_ENUM_NO_DOT < %t.enum.txt
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_QUAL_DOT_1 > %t.enum.txt
-// RUN: %FileCheck %s -check-prefix=FOO_ENUM_DOT_INVALID < %t.enum.txt
+// RUN: %FileCheck %s -check-prefix=FOO_ENUM_DOT < %t.enum.txt
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_QUAL_DOT_2 > %t.enum.txt
// RUN: %FileCheck %s -check-prefix=BAR_ENUM_DOT < %t.enum.txt
@@ -127,17 +127,6 @@
// FOO_ENUM_DOT_CONTEXT-NEXT: Decl[StaticVar]/CurrNominal: allCases[#[FooEnum]#]{{; name=.+$}}
// FOO_ENUM_DOT_CONTEXT-NEXT: End completions
-// FOO_ENUM_DOT_INVALID: Begin completions
-// FOO_ENUM_DOT_INVALID-NEXT: Keyword[self]/CurrNominal: self[#FooEnum.Type#]; name=self
-// FOO_ENUM_DOT_INVALID-NEXT: Keyword/CurrNominal: Type[#FooEnum.Type#]; name=Type
-// FOO_ENUM_DOT_INVALID-NEXT: Decl[EnumElement]/CurrNominal: Foo1[#FooEnum#]{{; name=.+$}}
-// FOO_ENUM_DOT_INVALID-NEXT: Decl[EnumElement]/CurrNominal: Foo2[#FooEnum#]{{; name=.+$}}
-// FOO_ENUM_DOT_INVALID-NEXT: Decl[StaticVar]/CurrNominal: alias1[#FooEnum#]{{; name=.+$}}
-// FOO_ENUM_DOT_INVALID-NEXT: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): FooEnum#})[#(into: inout Hasher) -> Void#]{{; name=.+$}}
-// FOO_ENUM_DOT_INVALID-NEXT: Decl[TypeAlias]/CurrNominal: AllCases[#[FooEnum]#]{{; name=.+$}}
-// FOO_ENUM_DOT_INVALID-NEXT: Decl[StaticVar]/CurrNominal: allCases[#[FooEnum]#]{{; name=.+$}}
-// FOO_ENUM_DOT_INVALID-NEXT: End completions
-
// FOO_ENUM_DOT_ELEMENTS: Begin completions, 13 items
// FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: Foo1[#FooEnum#]{{; name=.+$}}
// FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: Foo2[#FooEnum#]{{; name=.+$}}
@@ -224,7 +213,7 @@
// BAR_ENUM_DOT-NEXT: Decl[EnumElement]/CurrNominal: Bar10({#Int#}, {#Float#})[#BarEnum#]{{; name=.+$}}
// BAR_ENUM_DOT-NEXT: Decl[EnumElement]/CurrNominal: Bar11({#Int#}, {#(Float)#})[#BarEnum#]{{; name=.+$}}
// BAR_ENUM_DOT-NEXT: Decl[EnumElement]/CurrNominal: Bar12({#Int#}, {#(Float, Double)#})[#BarEnum#]{{; name=.+$}}
-// BAR_ENUM_DOT-NEXT: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: barInstanceFunc({#(self): &BarEnum#})[#() -> Void#]{{; name=.+$}}
+// BAR_ENUM_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: barInstanceFunc({#(self): &BarEnum#})[#() -> Void#]{{; name=.+$}}
// BAR_ENUM_DOT-NEXT: Decl[StaticVar]/CurrNominal: staticVar[#Int#]{{; name=.+$}}
// BAR_ENUM_DOT-NEXT: Decl[StaticMethod]/CurrNominal/TypeRelation[Invalid]: barStaticFunc()[#Void#]{{; name=.+$}}
// BAR_ENUM_DOT-NEXT: End completions
@@ -272,7 +261,7 @@
// BAZ_INT_ENUM_DOT-NEXT: Keyword/CurrNominal: Type[#BazEnum<Int>.Type#]; name=Type
// BAZ_INT_ENUM_DOT-NEXT: Decl[EnumElement]/CurrNominal: Baz1[#BazEnum<Int>#]{{; name=.+$}}
// BAZ_INT_ENUM_DOT-NEXT: Decl[EnumElement]/CurrNominal: Baz2({#Int#})[#BazEnum<Int>#]{{; name=.+$}}
-// BAZ_INT_ENUM_DOT-NEXT: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: bazInstanceFunc({#(self): &BazEnum<Int>#})[#() -> Void#]{{; name=.+$}}
+// BAZ_INT_ENUM_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: bazInstanceFunc({#(self): &BazEnum<Int>#})[#() -> Void#]{{; name=.+$}}
// BAZ_INT_ENUM_DOT-NEXT: Decl[StaticVar]/CurrNominal: staticVar[#Int#]{{; name=.+$}}
// BAZ_INT_ENUM_DOT-NEXT: Decl[StaticVar]/CurrNominal: staticVarT[#Int#]{{; name=.+$}}
// BAZ_INT_ENUM_DOT-NEXT: Decl[StaticMethod]/CurrNominal/TypeRelation[Invalid]: bazStaticFunc()[#Void#]{{; name=.+$}}
@@ -286,7 +275,7 @@
// BAZ_T_ENUM_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: bazInstanceFunc({#(self): &BazEnum<_>#})[#() -> Void#]{{; name=.+$}}
// BAZ_T_ENUM_DOT-NEXT: Decl[StaticVar]/CurrNominal: staticVar[#Int#]{{; name=.+$}}
// BAZ_T_ENUM_DOT-NEXT: Decl[StaticVar]/CurrNominal: staticVarT[#_#]{{; name=.+$}}
-// BAZ_T_ENUM_DOT-NEXT: Decl[StaticMethod]/CurrNominal: bazStaticFunc()[#Void#]{{; name=.+$}}
+// BAZ_T_ENUM_DOT-NEXT: Decl[StaticMethod]/CurrNominal/TypeRelation[Invalid]: bazStaticFunc()[#Void#]{{; name=.+$}}
// BAZ_T_ENUM_DOT-NEXT: End completions
enum QuxEnum : Int {
@@ -316,7 +305,7 @@
// QUX_ENUM_DOT-NEXT: Decl[EnumElement]/CurrNominal: Qux2[#QuxEnum#]{{; name=.+$}}
// QUX_ENUM_DOT-NEXT: Decl[TypeAlias]/CurrNominal: RawValue[#Int#]{{; name=.+$}}
// QUX_ENUM_DOT-NEXT: Decl[Constructor]/CurrNominal: init({#rawValue: Int#})[#QuxEnum?#]{{; name=.+$}}
-// QUX_ENUM_DOT-NEXT: Decl[InstanceMethod]/Super/IsSystem/TypeRelation[Invalid]: hash({#(self): QuxEnum#})[#(into: inout Hasher) -> Void#]{{; name=.+$}}
+// QUX_ENUM_DOT-NEXT: Decl[InstanceMethod]/Super/IsSystem: hash({#(self): QuxEnum#})[#(into: inout Hasher) -> Void#]{{; name=.+$}}
// QUX_ENUM_DOT-NEXT: End completions
func freeFunc() {}
diff --git a/test/IDE/complete_exception.swift b/test/IDE/complete_exception.swift
index a5cef6b..89f02c1 100644
--- a/test/IDE/complete_exception.swift
+++ b/test/IDE/complete_exception.swift
@@ -108,16 +108,16 @@
func test003() {
do {} catch Error4.#^CATCH2^#
// CATCH2: Begin completions
-// CATCH2: Decl[EnumElement]/CurrNominal: E1[#Error4#]{{; name=.+$}}
-// CATCH2: Decl[EnumElement]/CurrNominal: E2({#Int32#})[#Error4#]{{; name=.+$}}
+// CATCH2: Decl[EnumElement]/CurrNominal/TypeRelation[Convertible]: E1[#Error4#]{{; name=.+$}}
+// CATCH2: Decl[EnumElement]/CurrNominal/TypeRelation[Convertible]: E2({#Int32#})[#Error4#]{{; name=.+$}}
// CATCH2: End completions
}
func test004() {
throw Error4.#^THROW2^#
// THROW2: Begin completions
-// THROW2: Decl[EnumElement]/CurrNominal: E1[#Error4#]{{; name=.+$}}
-// THROW2: Decl[EnumElement]/CurrNominal: E2({#Int32#})[#Error4#]{{; name=.+$}}
+// THROW2: Decl[EnumElement]/CurrNominal/TypeRelation[Convertible]: E1[#Error4#]{{; name=.+$}}
+// THROW2: Decl[EnumElement]/CurrNominal/TypeRelation[Convertible]: E2({#Int32#})[#Error4#]{{; name=.+$}}
// THROW2: End completions
}
@@ -131,8 +131,8 @@
func testInvalid() {
try throw Error4.#^THROW3^#
// THROW3: Begin completions
-// THROW3: Decl[EnumElement]/CurrNominal: E1[#Error4#]{{; name=.+$}}
-// THROW3: Decl[EnumElement]/CurrNominal: E2({#Int32#})[#Error4#]{{; name=.+$}}
+// THROW3: Decl[EnumElement]/CurrNominal/TypeRelation[Convertible]: E1[#Error4#]{{; name=.+$}}
+// THROW3: Decl[EnumElement]/CurrNominal/TypeRelation[Convertible]: E2({#Int32#})[#Error4#]{{; name=.+$}}
// THROW3: End completions
}
diff --git a/test/Interop/Cxx/operators/Inputs/member-inline.h b/test/Interop/Cxx/operators/Inputs/member-inline.h
index 8204aa0..4333f6e 100644
--- a/test/Interop/Cxx/operators/Inputs/member-inline.h
+++ b/test/Interop/Cxx/operators/Inputs/member-inline.h
@@ -3,7 +3,7 @@
struct IntBox {
int value;
- IntBox operator+(IntBox rhs) { return IntBox{.value = value + rhs.value}; }
+ IntBox operator-(IntBox rhs) { return IntBox{.value = value - rhs.value}; }
};
#endif
diff --git a/test/Interop/Cxx/operators/member-inline-irgen.swift b/test/Interop/Cxx/operators/member-inline-irgen.swift
index 7976820..169c10d 100644
--- a/test/Interop/Cxx/operators/member-inline-irgen.swift
+++ b/test/Interop/Cxx/operators/member-inline-irgen.swift
@@ -5,7 +5,7 @@
import MemberInline
-public func add(_ lhs: inout IntBox, _ rhs: IntBox) -> IntBox { lhs + rhs }
+public func sub(_ lhs: inout IntBox, _ rhs: IntBox) -> IntBox { lhs - rhs }
-// CHECK: call [[RES:i32|i64]] [[NAME:@(_ZN6IntBoxplES_|"\?\?HIntBox@@QEAA\?AU0@U0@@Z")]](%struct.IntBox* {{%[0-9]+}}, {{i32|\[1 x i32\]|i64|%struct.IntBox\* byval align 4}} {{%[0-9]+}})
+// CHECK: call [[RES:i32|i64]] [[NAME:@(_ZN6IntBoxmiES_|"\?\?GIntBox@@QEAA\?AU0@U0@@Z")]](%struct.IntBox* {{%[0-9]+}}, {{i32|\[1 x i32\]|i64|%struct.IntBox\* byval align 4}} {{%[0-9]+}})
// CHECK: define linkonce_odr [[RES]] [[NAME]](%struct.IntBox* %this, {{i32 %rhs.coerce|\[1 x i32\] %rhs.coerce|i64 %rhs.coerce|%struct.IntBox\* byval\(%struct.IntBox\) align 4 %rhs}})
diff --git a/test/Interop/Cxx/operators/member-inline-module-interface.swift b/test/Interop/Cxx/operators/member-inline-module-interface.swift
index aef362f..b90893a 100644
--- a/test/Interop/Cxx/operators/member-inline-module-interface.swift
+++ b/test/Interop/Cxx/operators/member-inline-module-interface.swift
@@ -1,5 +1,5 @@
// RUN: %target-swift-ide-test -print-module -module-to-print=MemberInline -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s
// CHECK: struct IntBox {
-// CHECK: static func + (lhs: inout IntBox, rhs: IntBox) -> IntBox
+// CHECK: static func - (lhs: inout IntBox, rhs: IntBox) -> IntBox
// CHECK: }
diff --git a/test/Interop/Cxx/operators/member-inline-silgen.swift b/test/Interop/Cxx/operators/member-inline-silgen.swift
index 96d89a4..3b88723 100644
--- a/test/Interop/Cxx/operators/member-inline-silgen.swift
+++ b/test/Interop/Cxx/operators/member-inline-silgen.swift
@@ -2,13 +2,13 @@
import MemberInline
-public func add(_ lhs: inout IntBox, _ rhs: IntBox) -> IntBox { lhs + rhs }
+public func sub(_ lhs: inout IntBox, _ rhs: IntBox) -> IntBox { lhs - rhs }
// CHECK: bb0([[SELF:%.*]] : $*IntBox, [[RHS:%.*]] : $IntBox):
// CHECK: [[SELFACCESS:%.*]] = begin_access [modify] [static] [[SELF]] : $*IntBox
-// CHECK: [[OP:%.*]] = function_ref [[NAME:@(_ZN6IntBoxplES_|\?\?HIntBox@@QEAA\?AU0@U0@@Z)]] : $@convention(c) (@inout IntBox, IntBox) -> IntBox
+// CHECK: [[OP:%.*]] = function_ref [[NAME:@(_ZN6IntBoxmiES_|\?\?GIntBox@@QEAA\?AU0@U0@@Z)]] : $@convention(c) (@inout IntBox, IntBox) -> IntBox
// CHECK: apply [[OP]]([[SELFACCESS]], [[RHS]]) : $@convention(c) (@inout IntBox, IntBox) -> IntBox
// CHECK: end_access [[SELFACCESS]] : $*IntBox
-// CHECK: sil [clang IntBox."+"] [[NAME]] : $@convention(c) (@inout IntBox, IntBox) -> IntBox
+// CHECK: sil [clang IntBox."-"] [[NAME]] : $@convention(c) (@inout IntBox, IntBox) -> IntBox
diff --git a/test/Interop/Cxx/operators/member-inline-typechecker.swift b/test/Interop/Cxx/operators/member-inline-typechecker.swift
index 635875a..3b19898 100644
--- a/test/Interop/Cxx/operators/member-inline-typechecker.swift
+++ b/test/Interop/Cxx/operators/member-inline-typechecker.swift
@@ -5,4 +5,4 @@
var lhs = IntBox(value: 42)
let rhs = IntBox(value: 23)
-let resultPlus = lhs + rhs
+let resultPlus = lhs - rhs
diff --git a/test/Interop/Cxx/operators/member-inline.swift b/test/Interop/Cxx/operators/member-inline.swift
index 0313d84..f3b1e29 100644
--- a/test/Interop/Cxx/operators/member-inline.swift
+++ b/test/Interop/Cxx/operators/member-inline.swift
@@ -14,9 +14,9 @@
var lhs = IntBox(value: 42)
let rhs = IntBox(value: 23)
- let result = lhs + rhs
+ let result = lhs - rhs
- expectEqual(65, result.value)
+ expectEqual(19, result.value)
}
runAllTests()
diff --git a/test/Interpreter/generic_ref_counts.swift b/test/Interpreter/generic_ref_counts.swift
index 44e6307..4f9a469 100644
--- a/test/Interpreter/generic_ref_counts.swift
+++ b/test/Interpreter/generic_ref_counts.swift
@@ -1,5 +1,6 @@
// RUN: %target-run-simple-swift | %FileCheck %s
// REQUIRES: executable_test
+// XFAIL: OS=openbsd
import Swift
diff --git a/test/SILGen/Inputs/replace_opaque_type_public_assoc_type_m.swift b/test/SILGen/Inputs/replace_opaque_type_public_assoc_type_m.swift
new file mode 100644
index 0000000..c2120db
--- /dev/null
+++ b/test/SILGen/Inputs/replace_opaque_type_public_assoc_type_m.swift
@@ -0,0 +1,11 @@
+public protocol Gesture {
+ associatedtype Body: Gesture
+ var body: Body { get }
+
+ associatedtype Value
+ var value: Value { get }
+}
+
+extension Gesture {
+ public var value: Body.Value { return body.value }
+}
diff --git a/test/SILGen/replace_opaque_type_public_assoc_type.swift b/test/SILGen/replace_opaque_type_public_assoc_type.swift
new file mode 100644
index 0000000..c256b32
--- /dev/null
+++ b/test/SILGen/replace_opaque_type_public_assoc_type.swift
@@ -0,0 +1,14 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -disable-availability-checking -emit-module-path %t/replace_opaque_type_public_assoc_type_m.swiftmodule %S/Inputs/replace_opaque_type_public_assoc_type_m.swift
+// RUN: %target-swift-emit-silgen -disable-availability-checking -I %t %s -verify
+
+import replace_opaque_type_public_assoc_type_m
+
+struct PiggyBack: Gesture {
+ var action: () -> Void
+
+ var body: some Gesture {
+ action()
+ return self
+ }
+}
diff --git a/test/SourceKit/CodeComplete/complete_annotateddescription.swift.result b/test/SourceKit/CodeComplete/complete_annotateddescription.swift.result
index 0b2862f..c5c0db7 100644
--- a/test/SourceKit/CodeComplete/complete_annotateddescription.swift.result
+++ b/test/SourceKit/CodeComplete/complete_annotateddescription.swift.result
@@ -94,7 +94,7 @@
key.description: "<name>init</name>()",
key.typename: "<typeid.user>MyStruct</typeid.user>",
key.context: source.codecompletion.context.thisclass,
- key.typerelation: source.codecompletion.typerelation.unrelated,
+ key.typerelation: source.codecompletion.typerelation.unknown,
key.num_bytes_to_erase: 0,
key.associated_usrs: "s:29complete_annotateddescription8MyStructVACycfc",
key.modulename: "complete_annotateddescription"
@@ -106,7 +106,7 @@
key.description: "<name>labelName</name>(<callarg><callarg.label>_</callarg.label> <callarg.param>self</callarg.param>: <callarg.type><typeid.user>MyStruct</typeid.user></callarg.type></callarg>)",
key.typename: "(label: (<attribute>@autoclosure</attribute> () -> <typeid.sys>Int</typeid.sys>) -> <typeid.sys>Int</typeid.sys>) -> <typeid.sys>Void</typeid.sys>",
key.context: source.codecompletion.context.thisclass,
- key.typerelation: source.codecompletion.typerelation.unrelated,
+ key.typerelation: source.codecompletion.typerelation.unknown,
key.num_bytes_to_erase: 0,
key.associated_usrs: "s:29complete_annotateddescription8MyStructV9labelName0E0yS2iyXKXE_tF",
key.modulename: "complete_annotateddescription"
@@ -118,7 +118,7 @@
key.description: "<name>labelNameParamName</name>(<callarg><callarg.label>_</callarg.label> <callarg.param>self</callarg.param>: <callarg.type><typeid.user>MyStruct</typeid.user></callarg.type></callarg>)",
key.typename: "(label: (<keyword>inout</keyword> <typeid.sys>Int</typeid.sys>) <keyword>throws</keyword> -> <typeid.user>MyStruct</typeid.user>) -> <typeid.sys>Void</typeid.sys>",
key.context: source.codecompletion.context.thisclass,
- key.typerelation: source.codecompletion.typerelation.unrelated,
+ key.typerelation: source.codecompletion.typerelation.unknown,
key.num_bytes_to_erase: 0,
key.associated_usrs: "s:29complete_annotateddescription8MyStructV014labelNameParamF00E0yACSizKXE_tKF",
key.modulename: "complete_annotateddescription"
@@ -130,7 +130,7 @@
key.description: "<name>paramName</name>(<callarg><callarg.label>_</callarg.label> <callarg.param>self</callarg.param>: <callarg.type><typeid.user>MyStruct</typeid.user></callarg.type></callarg>)",
key.typename: "(<typeid.sys>Int</typeid.sys>) -> <typeid.sys>Void</typeid.sys>",
key.context: source.codecompletion.context.thisclass,
- key.typerelation: source.codecompletion.typerelation.unrelated,
+ key.typerelation: source.codecompletion.typerelation.unknown,
key.num_bytes_to_erase: 0,
key.associated_usrs: "s:29complete_annotateddescription8MyStructV9paramNameyySiF",
key.modulename: "complete_annotateddescription"
@@ -142,7 +142,7 @@
key.description: "<name>sameName</name>(<callarg><callarg.label>_</callarg.label> <callarg.param>self</callarg.param>: <callarg.type><typeid.user>MyStruct</typeid.user></callarg.type></callarg>)",
key.typename: "(label: <typeid.sys>Int</typeid.sys>) -> <typeid.sys>Void</typeid.sys>",
key.context: source.codecompletion.context.thisclass,
- key.typerelation: source.codecompletion.typerelation.unrelated,
+ key.typerelation: source.codecompletion.typerelation.unknown,
key.num_bytes_to_erase: 0,
key.associated_usrs: "s:29complete_annotateddescription8MyStructV8sameName5labelySi_tF",
key.modulename: "complete_annotateddescription"
diff --git a/test/SourceKit/CodeComplete/complete_docbrief_1.swift b/test/SourceKit/CodeComplete/complete_docbrief_1.swift
index 0941019..1b71266 100644
--- a/test/SourceKit/CodeComplete/complete_docbrief_1.swift
+++ b/test/SourceKit/CodeComplete/complete_docbrief_1.swift
@@ -35,7 +35,7 @@
// CHECK-NEXT: key.typename: "Void",
// CHECK-NEXT: key.doc.brief: "This is a doc comment of P.bar",
// CHECK-NEXT: key.context: source.codecompletion.context.superclass,
-// CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unrelated,
+// CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unknown,
// CHECK-NEXT: key.num_bytes_to_erase: 0,
// CHECK-NEXT: key.associated_usrs: "s:12DocBriefTest1PPAAE3baryyF",
// CHECK-NEXT: key.modulename: "DocBriefTest"
@@ -48,7 +48,7 @@
// CHECK-NEXT: key.typename: "Void",
// CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo",
// CHECK-NEXT: key.context: source.codecompletion.context.thisclass,
-// CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unrelated,
+// CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unknown,
// CHECK-NEXT: key.num_bytes_to_erase: 0,
// CHECK-NEXT: key.associated_usrs: "s:12DocBriefTest1SV3fooyyF s:12DocBriefTest1PP3fooyyF",
// CHECK-NEXT: key.modulename: "DocBriefTest"
diff --git a/test/SourceKit/CodeComplete/complete_docbrief_2.swift b/test/SourceKit/CodeComplete/complete_docbrief_2.swift
index b65f0d3..744cdec 100644
--- a/test/SourceKit/CodeComplete/complete_docbrief_2.swift
+++ b/test/SourceKit/CodeComplete/complete_docbrief_2.swift
@@ -39,7 +39,7 @@
// CHECK-NEXT: key.typename: "Void",
// CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo",
// CHECK-NEXT: key.context: source.codecompletion.context.thisclass,
-// CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unrelated,
+// CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unknown,
// CHECK-NEXT: key.num_bytes_to_erase: 0,
// CHECK-NEXT: key.associated_usrs: "s:12DocBriefUser1SV3fooyyF s:12DocBriefTest1PP3fooyyF",
// CHECK-NEXT: key.modulename: "DocBriefUser"
diff --git a/test/SourceKit/CodeComplete/complete_docbrief_3.swift b/test/SourceKit/CodeComplete/complete_docbrief_3.swift
index a329824..a346c86 100644
--- a/test/SourceKit/CodeComplete/complete_docbrief_3.swift
+++ b/test/SourceKit/CodeComplete/complete_docbrief_3.swift
@@ -40,7 +40,7 @@
// CHECK-NEXT: key.typename: "Void",
// CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo",
// CHECK-NEXT: key.context: source.codecompletion.context.thisclass,
-// CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unrelated,
+// CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unknown,
// CHECK-NEXT: key.num_bytes_to_erase: 0,
// CHECK-NEXT: key.associated_usrs: "s:12DocBriefTest1SV3fooyyF s:12DocBriefTest1PP3fooyyF",
// CHECK-NEXT: key.modulename: "DocBriefTest"
diff --git a/test/SourceKit/CodeComplete/complete_member.swift b/test/SourceKit/CodeComplete/complete_member.swift
index 3750d12..6681e6e 100644
--- a/test/SourceKit/CodeComplete/complete_member.swift
+++ b/test/SourceKit/CodeComplete/complete_member.swift
@@ -51,7 +51,7 @@
// CHECK-OPTIONAL-NEXT: key.description: "fooInstanceFunc1(a: Int)",
// CHECK-OPTIONAL-NEXT: key.typename: "Double",
// CHECK-OPTIONAL-NEXT: key.context: source.codecompletion.context.thisclass,
-// CHECK-OPTIONAL-NEXT: key.typerelation: source.codecompletion.typerelation.unrelated,
+// CHECK-OPTIONAL-NEXT: key.typerelation: source.codecompletion.typerelation.unknown,
// CHECK-OPTIONAL-NEXT: key.num_bytes_to_erase: 1,
// CHECK-OPTIONAL-NEXT: key.associated_usrs: "s:15complete_member11FooProtocolP16fooInstanceFunc1ySdSiF",
// CHECK-OPTIONAL-NEXT: key.modulename: "complete_member"
@@ -73,7 +73,7 @@
// CHECK-OVERRIDE_USR-NEXT: key.description: "foo()",
// CHECK-OVERRIDE_USR-NEXT: key.typename: "Void",
// CHECK-OVERRIDE_USR-NEXT: key.context: source.codecompletion.context.thisclass,
-// CHECK-OVERRIDE_USR-NEXT: key.typerelation: source.codecompletion.typerelation.unrelated,
+// CHECK-OVERRIDE_USR-NEXT: key.typerelation: source.codecompletion.typerelation.unknown,
// CHECK-OVERRIDE_USR-NEXT: key.num_bytes_to_erase: 0,
// CHECK-OVERRIDE_USR-NEXT: key.associated_usrs: "s:15complete_member7DerivedC3fooyyF s:15complete_member4BaseC3fooyyF",
// CHECK-OVERRIDE_USR-NEXT: key.modulename: "complete_member"
diff --git a/test/SourceKit/CodeComplete/complete_member.swift.response b/test/SourceKit/CodeComplete/complete_member.swift.response
index 12d8b87..7201bb6 100644
--- a/test/SourceKit/CodeComplete/complete_member.swift.response
+++ b/test/SourceKit/CodeComplete/complete_member.swift.response
@@ -7,7 +7,7 @@
key.description: "fooInstanceFunc0()",
key.typename: "Double",
key.context: source.codecompletion.context.thisclass,
- key.typerelation: source.codecompletion.typerelation.unrelated,
+ key.typerelation: source.codecompletion.typerelation.unknown,
key.num_bytes_to_erase: 0,
key.associated_usrs: "s:15complete_member11FooProtocolP16fooInstanceFunc0SdyF",
key.modulename: "complete_member"
@@ -19,7 +19,7 @@
key.description: "fooInstanceFunc1(a: Int)",
key.typename: "Double",
key.context: source.codecompletion.context.thisclass,
- key.typerelation: source.codecompletion.typerelation.unrelated,
+ key.typerelation: source.codecompletion.typerelation.unknown,
key.num_bytes_to_erase: 0,
key.associated_usrs: "s:15complete_member11FooProtocolP16fooInstanceFunc1ySdSiF",
key.modulename: "complete_member"
@@ -32,7 +32,7 @@
key.typename: "Int",
key.doc.brief: "fooInstanceVar Aaa. Bbb.",
key.context: source.codecompletion.context.thisclass,
- key.typerelation: source.codecompletion.typerelation.unrelated,
+ key.typerelation: source.codecompletion.typerelation.unknown,
key.num_bytes_to_erase: 0,
key.associated_usrs: "s:15complete_member11FooProtocolP14fooInstanceVarSivp",
key.modulename: "complete_member"
diff --git a/test/SourceKit/CodeComplete/complete_optionalmethod.swift.response b/test/SourceKit/CodeComplete/complete_optionalmethod.swift.response
index 9dbd9a8..682f5f5 100644
--- a/test/SourceKit/CodeComplete/complete_optionalmethod.swift.response
+++ b/test/SourceKit/CodeComplete/complete_optionalmethod.swift.response
@@ -7,7 +7,7 @@
key.description: "optionalMethod?()",
key.typename: "Int",
key.context: source.codecompletion.context.thisclass,
- key.typerelation: source.codecompletion.typerelation.unrelated,
+ key.typerelation: source.codecompletion.typerelation.unknown,
key.num_bytes_to_erase: 0,
key.associated_usrs: "c:@M@complete_optionalmethod@objc(pl)Proto(im)optionalMethod",
key.modulename: "complete_optionalmethod"
diff --git a/test/stdlib/ManagedBuffer.swift b/test/stdlib/ManagedBuffer.swift
index 24d288c..0d69197 100644
--- a/test/stdlib/ManagedBuffer.swift
+++ b/test/stdlib/ManagedBuffer.swift
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
+// XFAIL: OS=openbsd
import StdlibUnittest
diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp
index c24e17a..4852a6f 100644
--- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp
+++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp
@@ -157,8 +157,6 @@
return results;
}
-static StringRef copyString(llvm::BumpPtrAllocator &allocator, StringRef str);
-
bool SourceKit::CodeCompletion::addCustomCompletions(
CompletionSink &sink, std::vector<Completion *> &completions,
ArrayRef<CustomCompletionInfo> customCompletions,
@@ -405,12 +403,6 @@
// CodeCompletionOrganizer::Impl utilities
//===----------------------------------------------------------------------===//
-static StringRef copyString(llvm::BumpPtrAllocator &allocator, StringRef str) {
- char *newStr = allocator.Allocate<char>(str.size());
- std::copy(str.begin(), str.end(), newStr);
- return StringRef(newStr, str.size());
-}
-
static std::unique_ptr<Group> make_group(StringRef name) {
auto g = std::make_unique<Group>();
g->name = name.str();
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
index f59c9d0..0cb600d 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
@@ -674,6 +674,7 @@
static UIdent PlatformOSXAppExt("source.availability.platform.osx_app_extension");
static UIdent PlatformtvOSAppExt("source.availability.platform.tvos_app_extension");
static UIdent PlatformWatchOSAppExt("source.availability.platform.watchos_app_extension");
+ static UIdent PlatformOpenBSD("source.availability.platform.openbsd");
std::vector<const DeclAttribute*> Scratch;
for (auto Attr : getDeclAttributes(D, Scratch)) {
@@ -702,6 +703,8 @@
PlatformUID = PlatformtvOSAppExt; break;
case PlatformKind::watchOSApplicationExtension:
PlatformUID = PlatformWatchOSAppExt; break;
+ case PlatformKind::OpenBSD:
+ PlatformUID = PlatformOpenBSD; break;
}
AvailableAttrInfo Info;