Merge pull request #13926 from xedin/rdar-26060144
[Runtime/ABI] Replace `emitTypeFieldAccessor` with a single runtime method
diff --git a/include/swift/Driver/Compilation.h b/include/swift/Driver/Compilation.h
index c2a5513..96112d7 100644
--- a/include/swift/Driver/Compilation.h
+++ b/include/swift/Driver/Compilation.h
@@ -161,6 +161,9 @@
/// redundant work.
bool EnableBatchMode;
+ /// Provides a randomization seed to batch-mode partitioning, for debugging.
+ unsigned BatchSeed;
+
/// True if temporary files should not be deleted.
bool SaveTemps;
@@ -203,6 +206,7 @@
unsigned NumberOfParallelCommands = 1,
bool EnableIncrementalBuild = false,
bool EnableBatchMode = false,
+ unsigned BatchSeed = 0,
bool SkipTaskExecution = false,
bool SaveTemps = false,
bool ShowDriverTimeCompilation = false,
diff --git a/include/swift/Driver/Driver.h b/include/swift/Driver/Driver.h
index dab4b8c..e957a40 100644
--- a/include/swift/Driver/Driver.h
+++ b/include/swift/Driver/Driver.h
@@ -156,6 +156,9 @@
/// Indicates whether the driver should check that the input files exist.
bool CheckInputFilesExist = true;
+ /// Provides a randomization seed to batch-mode partitioning, for debugging.
+ unsigned DriverBatchSeed = 0;
+
public:
Driver(StringRef DriverExecutable, StringRef Name,
ArrayRef<const char *> Args, DiagnosticEngine &Diags);
diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td
index d1c1030..0f2d9df 100644
--- a/include/swift/Option/Options.td
+++ b/include/swift/Option/Options.td
@@ -98,6 +98,9 @@
HelpText<"Show every step in the lifecycle of driver jobs">;
def driver_use_filelists : Flag<["-"], "driver-use-filelists">,
InternalDebugOpt, HelpText<"Pass input files as filelists whenever possible">;
+def driver_batch_seed : Separate<["-"], "driver-batch-seed">,
+ InternalDebugOpt,
+ HelpText<"Use the given seed value to randomize batch-mode partitions">;
def driver_always_rebuild_dependents :
Flag<["-"], "driver-always-rebuild-dependents">, InternalDebugOpt,
diff --git a/include/swift/SILOptimizer/Utils/Local.h b/include/swift/SILOptimizer/Utils/Local.h
index d6ebd5c..9ef601c 100644
--- a/include/swift/SILOptimizer/Utils/Local.h
+++ b/include/swift/SILOptimizer/Utils/Local.h
@@ -161,8 +161,6 @@
bool tryCheckedCastBrJumpThreading(SILFunction *Fn, DominanceInfo *DT,
SmallVectorImpl<SILBasicBlock *> &BlocksForWorklist);
-void recalcDomTreeForCCBOpt(DominanceInfo *DT, SILFunction &F);
-
/// A structure containing callbacks that are called when an instruction is
/// removed or added.
struct InstModCallbacks {
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 17e9664..b9aa54a 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -5471,7 +5471,11 @@
// always delegating. This occurs if the struct type is not fixed layout,
// and the constructor is either inlinable or defined in another module.
if (Kind == BodyInitKind::None && isa<StructDecl>(NTD)) {
- if (NTD->isFormallyResilient() &&
+ // Note: This is specifically not using isFormallyResilient. We relax this
+ // rule for structs in non-resilient modules so that they can have inlinable
+ // constructors, as long as those constructors don't reference private
+ // declarations.
+ if (NTD->isResilient() &&
getResilienceExpansion() == ResilienceExpansion::Minimal) {
Kind = BodyInitKind::Delegating;
diff --git a/lib/Basic/PartsOfSpeech.def b/lib/Basic/PartsOfSpeech.def
index 05326b7..a134ab9 100644
--- a/lib/Basic/PartsOfSpeech.def
+++ b/lib/Basic/PartsOfSpeech.def
@@ -370,7 +370,6 @@
VERB(hand)
VERB(handle)
VERB(hang)
-VERB(hang)
VERB(happen)
VERB(harass)
VERB(harm)
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 57c2a15..f091fee 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -4511,15 +4511,15 @@
}
Decl *VisitObjCInterfaceDecl(const clang::ObjCInterfaceDecl *decl) {
- auto createRootClass = [=](Identifier name,
- DeclContext *dc = nullptr) -> ClassDecl * {
+ auto createFakeRootClass = [=](Identifier name,
+ DeclContext *dc = nullptr) -> ClassDecl * {
if (!dc) {
dc = Impl.getClangModuleForDecl(decl->getCanonicalDecl(),
/*allowForwardDeclaration=*/true);
}
auto result = Impl.createDeclWithClangNode<ClassDecl>(decl,
- AccessLevel::Open,
+ AccessLevel::Public,
SourceLoc(), name,
SourceLoc(), None,
nullptr, dc);
@@ -4547,7 +4547,7 @@
const ClassDecl *nsObjectDecl =
nsObjectTy->getClassOrBoundGenericClass();
- auto result = createRootClass(Impl.SwiftContext.Id_Protocol,
+ auto result = createFakeRootClass(Impl.SwiftContext.Id_Protocol,
nsObjectDecl->getDeclContext());
result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
return result;
@@ -4579,7 +4579,7 @@
if (Impl.ImportForwardDeclarations) {
// Fake it by making an unavailable opaque @objc root class.
- auto result = createRootClass(name);
+ auto result = createFakeRootClass(name);
result->setImplicit();
auto attr = AvailableAttr::createPlatformAgnostic(Impl.SwiftContext,
"This Objective-C class has only been forward-declared; "
@@ -4602,13 +4602,16 @@
if (declaredNative && nativeDecl)
return nativeDecl;
+ auto access = AccessLevel::Open;
+ if (decl->hasAttr<clang::ObjCSubclassingRestrictedAttr>() &&
+ Impl.SwiftContext.isSwiftVersionAtLeast(5)) {
+ access = AccessLevel::Public;
+ }
+
// Create the class declaration and record it.
- auto result = Impl.createDeclWithClangNode<ClassDecl>(decl,
- AccessLevel::Open,
- Impl.importSourceLoc(decl->getLocStart()),
- name,
- Impl.importSourceLoc(decl->getLocation()),
- None, nullptr, dc);
+ auto result = Impl.createDeclWithClangNode<ClassDecl>(
+ decl, access, Impl.importSourceLoc(decl->getLocStart()), name,
+ Impl.importSourceLoc(decl->getLocation()), None, nullptr, dc);
// Import generic arguments, if any.
if (auto gpImportResult = importObjCGenericParams(decl, dc)) {
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index 7360d18..f43a17a 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -42,6 +42,10 @@
#include "CompilationRecord.h"
+// Batch-mode has a sub-mode for testing that randomizes batch partitions,
+// by user-provided seed. That is the only thing randomized here.
+#include <random>
+
using namespace swift;
using namespace swift::sys;
using namespace swift::driver;
@@ -97,6 +101,7 @@
unsigned NumberOfParallelCommands,
bool EnableIncrementalBuild,
bool EnableBatchMode,
+ unsigned BatchSeed,
bool SkipTaskExecution,
bool SaveTemps,
bool ShowDriverTimeCompilation,
@@ -112,6 +117,7 @@
SkipTaskExecution(SkipTaskExecution),
EnableIncrementalBuild(EnableIncrementalBuild),
EnableBatchMode(EnableBatchMode),
+ BatchSeed(BatchSeed),
SaveTemps(SaveTemps),
ShowDriverTimeCompilation(ShowDriverTimeCompilation),
Stats(std::move(StatsReporter)) {
@@ -120,7 +126,8 @@
static bool writeFilelistIfNecessary(const Job *job, DiagnosticEngine &diags);
using CommandSet = llvm::SmallPtrSet<const Job *, 16>;
-
+using CommandSetVector = llvm::SetVector<const Job*>;
+using BatchPartition = std::vector<std::vector<const Job*>>;
using InputInfoMap = llvm::SmallMapVector<const llvm::opt::Arg *,
CompileJobAction::InputInfo, 16>;
@@ -140,7 +147,7 @@
/// A temporary buffer to hold commands that were scheduled but haven't been
/// added to the Task Queue yet, because we might try batching them together
/// first.
- CommandSet PendingExecution;
+ CommandSetVector PendingExecution;
/// Set of synthetic BatchJobs that serve to cluster subsets of jobs waiting
/// in PendingExecution. Also used to identify (then unpack) BatchJobs back
@@ -680,7 +687,8 @@
/// Insert all jobs in \p Cmds (of descriptive name \p Kind) to the \c
/// TaskQueue, and clear \p Cmds.
- void transferJobsToTaskQueue(CommandSet &Cmds, StringRef Kind) {
+ template <typename Container>
+ void transferJobsToTaskQueue(Container &Cmds, StringRef Kind) {
for (const Job *Cmd : Cmds) {
if (Comp.ShowJobLifecycle)
llvm::outs() << "Adding " << Kind
@@ -694,8 +702,8 @@
/// Partition the jobs in \c PendingExecution into those that are \p
/// Batchable and those that are \p NonBatchable, clearing \p
/// PendingExecution.
- void getPendingBatchableJobs(CommandSet &Batchable,
- CommandSet &NonBatchable) {
+ void getPendingBatchableJobs(CommandSetVector &Batchable,
+ CommandSetVector &NonBatchable) {
for (const Job *Cmd : PendingExecution) {
if (Comp.getToolChain().jobIsBatchable(Comp, Cmd)) {
if (Comp.ShowJobLifecycle)
@@ -710,49 +718,83 @@
PendingExecution.clear();
}
- /// If \p CurrentBatch is nonempty, construct a new \c BatchJob from its
+ /// If \p Batch is nonempty, construct a new \c BatchJob from its
/// contents by calling \p ToolChain::constructBatchJob, then insert the
- /// new \c BatchJob into \p Batches and clear \p CurrentBatch.
+ /// new \c BatchJob into \p Batches.
void
- formBatchJobFromCurrentBatch(CommandSet &Batches,
- llvm::SetVector<const Job *> &CurrentBatch) {
- if (CurrentBatch.empty())
+ formBatchJobFromPartitionBatch(std::vector<const Job *> &Batches,
+ std::vector<const Job *> const &Batch) {
+ if (Batch.empty())
return;
if (Comp.ShowJobLifecycle)
llvm::outs() << "Forming batch job from "
- << CurrentBatch.size() << " constituents\n";
+ << Batch.size() << " constituents\n";
auto const &TC = Comp.getToolChain();
- auto J = TC.constructBatchJob(CurrentBatch.getArrayRef(), Comp);
+ auto J = TC.constructBatchJob(Batch, Comp);
if (J)
- Batches.insert(Comp.addJob(std::move(J)));
- CurrentBatch.clear();
+ Batches.push_back(Comp.addJob(std::move(J)));
}
- /// Return true iff \p Cmd can be expanded by \p CurrentBatch, meaning
- /// that \p CurrentBatch is smaller than \p TargetBatchSize and \p Cmd
- /// is batch-combinable with the equivalence class of \p CurrentBatch
- /// (as represented by element 0 of \p CurrentBatch).
- bool canExpandBatch(const Job *Cmd,
- llvm::SetVector<const Job *> &CurrentBatch,
- size_t TargetBatchSize) {
- auto const &TC = Comp.getToolChain();
- return (CurrentBatch.empty() ||
- (TC.jobsAreBatchCombinable(Comp, Cmd, CurrentBatch[0]) &&
- CurrentBatch.size() < TargetBatchSize));
+ /// Inspect current batch \p i of the \p Partition currently being built
+ /// and, if that batch is "full" (in the sense of holding an evenly-divided
+ /// portion of NumJobs) then advance \p i to the next batch index in the
+ /// partition.
+ void maybeAdvanceToNextPartition(size_t &i,
+ BatchPartition const &Partition,
+ size_t NumJobs) {
+ assert(i < Partition.size());
+ size_t Remainder = NumJobs % Partition.size();
+ size_t TargetSize = NumJobs / Partition.size();
+ // Spread remainder evenly across partitions by adding 1 to the target
+ // size of the first Remainder of them.
+ if (i < Remainder)
+ TargetSize++;
+ if (Partition[i].size() >= TargetSize)
+ ++i;
+ assert(i < Partition.size());
}
- /// If \p CurrentBatch can't be expanded with \p Cmd, form a new \c BatchJob
- /// from \p CurrentBatch, add it to \p Batches, and reset\p CurrentBatch;
- /// then in either case, insert \p Cmd into \p CurrentBatch.
- void expandBatch(const Job *Cmd,
- CommandSet &Batches,
- llvm::SetVector<const Job *> &CurrentBatch,
- size_t TargetBatchSize) {
- if (!canExpandBatch(Cmd, CurrentBatch, TargetBatchSize)) {
- formBatchJobFromCurrentBatch(Batches, CurrentBatch);
+ /// Shuffle \p Batchable if -driver-batch-seed is nonzero.
+ void maybeShuffleBatchable(std::vector<const Job *> &Batchable) {
+ if (Comp.BatchSeed != 0) {
+ std::minstd_rand gen(Comp.BatchSeed);
+ std::shuffle(Batchable.begin(), Batchable.end(), gen);
}
- llvm::outs() << "Adding to batch: " << LogJob(Cmd) << "\n";
- CurrentBatch.insert(Cmd);
+ }
+
+ /// Create \c NumberOfParallelCommands batches and assign each job to a
+ /// batch either filling each partition in order or, if seeded with a
+ /// nonzero value, pseudo-randomly (but determinstically and nearly-evenly).
+ void partitionIntoBatches(std::vector<const Job *> Batchable,
+ BatchPartition &Partition) {
+ if (Comp.ShowJobLifecycle) {
+ llvm::outs() << "Found " << Batchable.size() << " batchable jobs\n";
+ llvm::outs() << "Forming into " << Partition.size() << " batches\n";
+ }
+
+ assert(Partition.size() > 0);
+ maybeShuffleBatchable(Batchable);
+
+ size_t i = 0;
+ auto const &TC = Comp.getToolChain();
+ for (const Job *Cmd : Batchable) {
+ maybeAdvanceToNextPartition(i, Partition, Batchable.size());
+ std::vector<const Job*> &P = Partition[i];
+ if (P.empty() || TC.jobsAreBatchCombinable(Comp, P[0], Cmd)) {
+ if (Comp.ShowJobLifecycle)
+ llvm::outs() << "Adding " << LogJob(Cmd)
+ << " to batch " << i << '\n';
+ P.push_back(Cmd);
+ } else {
+ // Strange but theoretically possible that we have a batchable job
+ // that's not combinable with others; tack a new batch on for it.
+ if (Comp.ShowJobLifecycle)
+ llvm::outs() << "Adding " << LogJob(Cmd)
+ << " to new batch " << Partition.size() << '\n';
+ Partition.push_back(std::vector<const Job*>());
+ Partition.back().push_back(Cmd);
+ }
+ }
}
/// Select jobs that are batch-combinable from \c PendingExecution, combine
@@ -768,25 +810,18 @@
return;
}
- // Partition the pending jobs.
- CommandSet Batchable, NonBatchable, Batches;
+ // Split the batchable from non-batchable pending jobs.
+ CommandSetVector Batchable, NonBatchable;
getPendingBatchableJobs(Batchable, NonBatchable);
- size_t TargetBatchSize = Batchable.size() / Comp.NumberOfParallelCommands;
- if (Comp.ShowJobLifecycle) {
- llvm::outs() << "Found " << Batchable.size() << " batchable jobs\n";
- llvm::outs() << "Aiming for batch size " << TargetBatchSize << '\n';
- }
+ // Partition the batchable jobs into sets.
+ BatchPartition Partition(Comp.NumberOfParallelCommands);
+ partitionIntoBatches(Batchable.takeVector(), Partition);
- // Batch the batchable jobs.
- llvm::SetVector<const Job *> CurrentBatch;
- for (const Job *Cmd : Batchable) {
- expandBatch(Cmd, Batches, CurrentBatch, TargetBatchSize);
- }
-
- // Form a residual incomplete batch if any jobs remain.
- if (!CurrentBatch.empty()) {
- formBatchJobFromCurrentBatch(Batches, CurrentBatch);
+ // Construct a BatchJob from each batch in the partition.
+ std::vector<const Job *> Batches;
+ for (auto const &Batch : Partition) {
+ formBatchJobFromPartitionBatch(Batches, Batch);
}
// Save batches so we can locate and decompose them on task-exit.
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index e3f7545..a567d8a 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -522,6 +522,12 @@
ArgList->hasArg(options::OPT_driver_show_incremental);
bool ShowJobLifecycle =
ArgList->hasArg(options::OPT_driver_show_job_lifecycle);
+ if (const Arg *A = ArgList->getLastArg(options::OPT_driver_batch_seed)) {
+ if (StringRef(A->getValue()).getAsInteger(10, DriverBatchSeed)) {
+ Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
+ A->getAsString(*ArgList), A->getValue());
+ }
+ }
bool Incremental = ArgList->hasArg(options::OPT_incremental);
if (ArgList->hasArg(options::OPT_whole_module_optimization)) {
@@ -684,6 +690,7 @@
NumberOfParallelCommands,
Incremental,
BatchMode,
+ DriverBatchSeed,
DriverSkipExecution,
SaveTemps,
ShowDriverTimeCompilation,
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index bd191de..c53f052 100644
--- a/lib/Driver/Job.cpp
+++ b/lib/Driver/Job.cpp
@@ -244,36 +244,44 @@
// from a JobAction that itself has InputActions sources, then we collect
// those up. Otherwise it's more correct to talk about our inputs as the
// outputs of our input-jobs.
- SmallVector<std::string, 4> Inputs;
+ SmallVector<StringRef, 4> Inputs;
+ SmallVector<StringRef, 4> Outputs = getOutput().getPrimaryOutputFilenames();
for (const Action *A : getSource().getInputs())
if (const auto *IA = dyn_cast<InputAction>(A))
Inputs.push_back(IA->getInputArg().getValue());
for (const Job *J : getInputs())
- for (const std::string &f : J->getOutput().getPrimaryOutputFilenames())
+ for (StringRef f : J->getOutput().getPrimaryOutputFilenames())
Inputs.push_back(f);
size_t limit = 3;
- size_t actual = Inputs.size();
- if (actual > limit) {
+ size_t actual_in = Inputs.size();
+ size_t actual_out = Outputs.size();
+ if (actual_in > limit) {
Inputs.erase(Inputs.begin() + limit, Inputs.end());
}
+ if (actual_out > limit) {
+ Outputs.erase(Outputs.begin() + limit, Outputs.end());
+ }
os << "{" << getSource().getClassName() << ": ";
- interleave(getOutput().getPrimaryOutputFilenames(),
+ interleave(Outputs,
[&](const std::string &Arg) {
os << llvm::sys::path::filename(Arg);
},
[&] { os << ' '; });
+ if (actual_out > limit) {
+ os << " ... " << (actual_out-limit) << " more";
+ }
os << " <= ";
interleave(Inputs,
[&](const std::string &Arg) {
os << llvm::sys::path::filename(Arg);
},
[&] { os << ' '; });
- if (actual > limit) {
- os << " ... " << (actual-limit) << " more";
+ if (actual_in > limit) {
+ os << " ... " << (actual_in-limit) << " more";
}
os << "}";
}
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index e0b28f2..4484168 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -544,10 +544,11 @@
public:
/// \brief Build a reference to the given declaration.
- Expr *buildDeclRef(ValueDecl *decl, DeclNameLoc loc, Type openedType,
+ Expr *buildDeclRef(OverloadChoice choice, DeclNameLoc loc, Type openedType,
ConstraintLocatorBuilder locator, bool implicit,
FunctionRefKind functionRefKind,
AccessSemantics semantics) {
+ auto *decl = choice.getDecl();
// Determine the declaration selected for this overloaded reference.
auto &ctx = cs.getASTContext();
@@ -612,7 +613,7 @@
if (auto fnConv = dyn_cast<FunctionConversionExpr>(refExpr))
refExpr = fnConv->getSubExpr();
- return forceUnwrapIfExpected(refExpr, decl, locator);
+ return forceUnwrapIfExpected(refExpr, choice, locator);
}
}
}
@@ -623,7 +624,7 @@
TypeExpr::createImplicitHack(loc.getBaseNameLoc(), baseTy, ctx);
cs.cacheExprTypes(base);
- return buildMemberRef(base, openedType, SourceLoc(), decl, loc,
+ return buildMemberRef(base, openedType, SourceLoc(), choice, loc,
openedFnType->getResult(), locator, locator,
implicit, functionRefKind, semantics,
/*isDynamic=*/false);
@@ -659,7 +660,7 @@
loc, implicit, semantics, type);
cs.cacheType(declRefExpr);
declRefExpr->setFunctionRefKind(functionRefKind);
- return forceUnwrapIfExpected(declRefExpr, decl, locator);
+ return forceUnwrapIfExpected(declRefExpr, choice, locator);
}
/// Describes an opened existential that has not yet been closed.
@@ -899,11 +900,12 @@
/// \brief Build a new member reference with the given base and member.
Expr *buildMemberRef(Expr *base, Type openedFullType, SourceLoc dotLoc,
- ValueDecl *member, DeclNameLoc memberLoc,
+ OverloadChoice choice, DeclNameLoc memberLoc,
Type openedType, ConstraintLocatorBuilder locator,
ConstraintLocatorBuilder memberLocator, bool Implicit,
FunctionRefKind functionRefKind,
AccessSemantics semantics, bool isDynamic) {
+ ValueDecl *member = choice.getDecl();
auto &tc = cs.getTypeChecker();
auto &context = tc.Context;
@@ -949,7 +951,7 @@
ref->setFunctionRefKind(functionRefKind);
auto *DSBI = cs.cacheType(new (context) DotSyntaxBaseIgnoredExpr(
base, dotLoc, ref, cs.getType(ref)));
- return forceUnwrapIfExpected(DSBI, member, memberLocator);
+ return forceUnwrapIfExpected(DSBI, choice, memberLocator);
}
// The formal type of the 'self' value for the member's declaration.
@@ -1088,8 +1090,9 @@
// We also need to handle the implicitly unwrap of the result
// of the called function if that's the type checking solution
// we ended up with.
- return forceUnwrapIfExpected(ref, member, memberLocator,
- member->getAttrs().hasAttribute<OptionalAttr>());
+ return forceUnwrapIfExpected(
+ ref, choice, memberLocator,
+ member->getAttrs().hasAttribute<OptionalAttr>());
}
// For types and properties, build member references.
@@ -1115,7 +1118,7 @@
cs.setType(memberRefExpr, simplifyType(openedType));
Expr *result = memberRefExpr;
closeExistential(result, locator);
- return forceUnwrapIfExpected(result, member, memberLocator);
+ return forceUnwrapIfExpected(result, choice, memberLocator);
}
// Handle all other references.
@@ -1135,7 +1138,7 @@
ApplyExpr *apply;
if (isa<ConstructorDecl>(member)) {
// FIXME: Provide type annotation.
- ref = forceUnwrapIfExpected(ref, member, memberLocator);
+ ref = forceUnwrapIfExpected(ref, choice, memberLocator);
apply = new (context) ConstructorRefCallExpr(ref, base);
} else if (!baseIsInstance && member->isInstanceMember()) {
// Reference to an unbound instance method.
@@ -1144,11 +1147,11 @@
cs.getType(ref));
cs.cacheType(result);
closeExistential(result, locator, /*force=*/openedExistential);
- return forceUnwrapIfExpected(result, member, memberLocator);
+ return forceUnwrapIfExpected(result, choice, memberLocator);
} else {
assert((!baseIsInstance || member->isInstanceMember()) &&
"can't call a static method on an instance");
- ref = forceUnwrapIfExpected(ref, member, memberLocator);
+ ref = forceUnwrapIfExpected(ref, choice, memberLocator);
apply = new (context) DotSyntaxCallExpr(ref, dotLoc, base);
if (Implicit) {
apply->setImplicit();
@@ -1449,10 +1452,10 @@
if (selected->choice.getKind() ==
OverloadChoiceKind::DynamicMemberLookup)
locatorKind = ConstraintLocator::Member;
-
- newSubscript = forceUnwrapIfExpected(
- newSubscript, selected->choice.getDecl(),
- locator.withPathElement(locatorKind));
+
+ newSubscript =
+ forceUnwrapIfExpected(newSubscript, selected->choice,
+ locator.withPathElement(locatorKind));
}
return newSubscript;
@@ -2471,8 +2474,9 @@
}
}
- bool shouldForceUnwrapResult(Decl *decl, ConstraintLocatorBuilder locator) {
- if (!decl->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>())
+ bool shouldForceUnwrapResult(OverloadChoice choice,
+ ConstraintLocatorBuilder locator) {
+ if (!choice.isImplicitlyUnwrappedValueOrReturnValue())
return false;
auto *choiceLocator = cs.getConstraintLocator(locator.withPathElement(
@@ -2481,10 +2485,10 @@
return solution.getDisjunctionChoice(choiceLocator);
}
- Expr *forceUnwrapIfExpected(Expr *expr, Decl *decl,
+ Expr *forceUnwrapIfExpected(Expr *expr, OverloadChoice choice,
ConstraintLocatorBuilder locator,
- bool forForcedOptional =false) {
- if (!shouldForceUnwrapResult(decl, locator))
+ bool forForcedOptional = false) {
+ if (!shouldForceUnwrapResult(choice, locator))
return expr;
// Force the expression if required for the solution.
@@ -2503,12 +2507,9 @@
cs.setType(expr, varDecl->getType());
return expr;
}
-
- auto choice = selected->choice;
- auto decl = choice.getDecl();
- return buildDeclRef(decl, expr->getNameLoc(), selected->openedFullType,
- locator, expr->isImplicit(),
+ return buildDeclRef(selected->choice, expr->getNameLoc(),
+ selected->openedFullType, locator, expr->isImplicit(),
expr->getFunctionRefKind(),
expr->getAccessSemantics());
}
@@ -2539,9 +2540,8 @@
auto locator = cs.getConstraintLocator(expr);
auto selected = getOverloadChoice(locator);
auto choice = selected.choice;
- auto decl = choice.getDecl();
- return buildDeclRef(decl, expr->getNameLoc(), selected.openedFullType,
+ return buildDeclRef(choice, expr->getNameLoc(), selected.openedFullType,
locator, expr->isImplicit(),
choice.getFunctionRefKind(),
AccessSemantics::Ordinary);
@@ -2566,7 +2566,7 @@
= selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
return buildMemberRef(
expr->getBase(), selected.openedFullType, expr->getDotLoc(),
- selected.choice.getDecl(), expr->getNameLoc(), selected.openedType,
+ selected.choice, expr->getNameLoc(), selected.openedType,
cs.getConstraintLocator(expr), memberLocator, expr->isImplicit(),
selected.choice.getFunctionRefKind(), expr->getAccessSemantics(),
isDynamic);
@@ -2594,7 +2594,6 @@
auto memberLocator = cs.getConstraintLocator(
expr, ConstraintLocator::UnresolvedMember);
auto selected = getOverloadChoice(memberLocator);
- auto member = selected.choice.getDecl();
// If the member came by optional unwrapping, then unwrap the base type.
if (selected.choice.getKind()
@@ -2614,7 +2613,7 @@
bool isDynamic
= selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
auto result = buildMemberRef(
- base, selected.openedFullType, expr->getDotLoc(), member,
+ base, selected.openedFullType, expr->getDotLoc(), selected.choice,
expr->getNameLoc(), selected.openedType,
cs.getConstraintLocator(expr), memberLocator, expr->isImplicit(),
selected.choice.getFunctionRefKind(), AccessSemantics::Ordinary,
@@ -2651,9 +2650,10 @@
Expr *applyCtorRefExpr(Expr *expr, Expr *base, SourceLoc dotLoc,
DeclNameLoc nameLoc, bool implicit,
ConstraintLocator *ctorLocator,
- ConstructorDecl *ctor,
- FunctionRefKind functionRefKind,
- Type openedType) {
+ OverloadChoice choice,
+ FunctionRefKind functionRefKind, Type openedType) {
+
+ auto *ctor = cast<ConstructorDecl>(choice.getDecl());
// If the member is a constructor, verify that it can be legally
// referenced from this base.
@@ -2665,7 +2665,7 @@
// constructor.
if (cs.getType(base)->is<AnyMetatypeType>()) {
return buildMemberRef(
- base, openedType, dotLoc, ctor, nameLoc, cs.getType(expr),
+ base, openedType, dotLoc, choice, nameLoc, cs.getType(expr),
ConstraintLocatorBuilder(cs.getConstraintLocator(expr)),
ctorLocator, implicit, functionRefKind, AccessSemantics::Ordinary,
/*isDynamic=*/false);
@@ -2731,10 +2731,9 @@
ConstraintLocator::ConstructorMember);
if (auto selected = getOverloadChoiceIfAvailable(ctorLocator)) {
auto choice = selected->choice;
- auto *ctor = cast<ConstructorDecl>(choice.getDecl());
- return applyCtorRefExpr(expr, base, dotLoc, nameLoc, implicit,
- ctorLocator, ctor, choice.getFunctionRefKind(),
- selected->openedFullType);
+ return applyCtorRefExpr(
+ expr, base, dotLoc, nameLoc, implicit, ctorLocator, choice,
+ choice.getFunctionRefKind(), selected->openedFullType);
}
// Determine the declaration selected for this overloaded reference.
@@ -2783,11 +2782,11 @@
case OverloadChoiceKind::DeclViaDynamic: {
bool isDynamic
= selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
- return buildMemberRef(
- base, selected.openedFullType, dotLoc, selected.choice.getDecl(),
- nameLoc, selected.openedType, cs.getConstraintLocator(expr),
- memberLocator, implicit, selected.choice.getFunctionRefKind(),
- AccessSemantics::Ordinary, isDynamic);
+ return buildMemberRef(base, selected.openedFullType, dotLoc,
+ selected.choice, nameLoc, selected.openedType,
+ cs.getConstraintLocator(expr), memberLocator,
+ implicit, selected.choice.getFunctionRefKind(),
+ AccessSemantics::Ordinary, isDynamic);
}
case OverloadChoiceKind::TupleIndex: {
@@ -4370,7 +4369,7 @@
baseTy = component.getComponentType();
resolvedComponents.push_back(component);
- if (shouldForceUnwrapResult(property, locator)) {
+ if (shouldForceUnwrapResult(foundDecl->choice, locator)) {
auto objectTy = getObjectType(baseTy);
auto loc = origComponent.getLoc();
component = KeyPathExpr::Component::forOptionalForce(objectTy, loc);
@@ -4451,7 +4450,7 @@
baseTy = component.getComponentType();
resolvedComponents.push_back(component);
- if (shouldForceUnwrapResult(subscript, locator)) {
+ if (shouldForceUnwrapResult(foundDecl->choice, locator)) {
auto objectTy = getObjectType(baseTy);
auto loc = origComponent.getLoc();
component = KeyPathExpr::Component::forOptionalForce(objectTy, loc);
@@ -7469,17 +7468,16 @@
// We have the constructor.
auto choice = selected->choice;
- auto decl = choice.getDecl();
// Consider the constructor decl reference expr 'implicit', but the
// constructor call expr itself has the apply's 'implicitness'.
bool isDynamic = choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
- Expr *declRef =
- buildMemberRef(fn, selected->openedFullType,
- /*dotLoc=*/SourceLoc(), decl, DeclNameLoc(fn->getEndLoc()),
- selected->openedType, locator, ctorLocator,
- /*Implicit=*/true, choice.getFunctionRefKind(),
- AccessSemantics::Ordinary, isDynamic);
+ Expr *declRef = buildMemberRef(fn, selected->openedFullType,
+ /*dotLoc=*/SourceLoc(), choice,
+ DeclNameLoc(fn->getEndLoc()),
+ selected->openedType, locator, ctorLocator,
+ /*Implicit=*/true, choice.getFunctionRefKind(),
+ AccessSemantics::Ordinary, isDynamic);
if (!declRef)
return nullptr;
declRef->setImplicit(apply->isImplicit());
@@ -8173,8 +8171,10 @@
ExprRewriter rewriter(cs, solution,
/*suppressDiagnostics=*/false);
+ auto choice =
+ OverloadChoice(openedFullType, witness, FunctionRefKind::SingleApply);
auto memberRef = rewriter.buildMemberRef(
- base, openedFullType, base->getStartLoc(), witness,
+ base, openedFullType, base->getStartLoc(), choice,
DeclNameLoc(base->getEndLoc()), openedType, dotLocator, dotLocator,
/*Implicit=*/true, FunctionRefKind::SingleApply,
AccessSemantics::Ordinary,
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 7a0e1e7..62cfdfc 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -1957,6 +1957,23 @@
}
bool OverloadChoice::isImplicitlyUnwrappedValueOrReturnValue() const {
- return isDecl() &&
- getDecl()->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
+ if (!isDecl())
+ return false;
+
+ auto *decl = getDecl();
+ if (!decl->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>())
+ return false;
+
+ auto itfType = decl->getInterfaceType();
+ if (!itfType->getAs<AnyFunctionType>())
+ return true;
+
+ switch (getFunctionRefKind()) {
+ case FunctionRefKind::Unapplied:
+ case FunctionRefKind::Compound:
+ return false;
+ case FunctionRefKind::SingleApply:
+ case FunctionRefKind::DoubleApply:
+ return true;
+ }
}
diff --git a/lib/Sema/OverloadChoice.h b/lib/Sema/OverloadChoice.h
index 1752343..4e4afac 100644
--- a/lib/Sema/OverloadChoice.h
+++ b/lib/Sema/OverloadChoice.h
@@ -190,6 +190,7 @@
result.BaseAndDeclKind.setPointer(base);
result.DeclOrKind = value;
result.DynamicNameAndFRK.setPointer(name);
+ result.DynamicNameAndFRK.setInt(FunctionRefKind::SingleApply);
return result;
}
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index cca4735..fc1e097 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -2276,14 +2276,10 @@
// If we entered an initializer context, contextualize any
// auto-closures we might have created.
- if (initContext) {
+ if (initContext && !hadError) {
// Check safety of error-handling in the declaration, too.
- if (!hadError) {
- checkInitializerErrorHandling(initContext, init);
- }
-
- if (!hadError)
- (void)contextualizeInitializer(initContext, init);
+ checkInitializerErrorHandling(initContext, init);
+ (void)contextualizeInitializer(initContext, init);
}
if (hadError) {
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index d9fb64b..06a1213 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -1620,9 +1620,12 @@
}
// An inlinable constructor in a class must always be delegating,
- // unless the class is formally '@_fixed_layout'.
- if (!isDelegating &&
- ClassD->isFormallyResilient() &&
+ // unless the class is '@_fixed_layout'.
+ // Note: This is specifically not using isFormallyResilient. We relax this
+ // rule for classes in non-resilient modules so that they can have inlinable
+ // constructors, as long as those constructors don't reference private
+ // declarations.
+ if (!isDelegating && ClassD->isResilient() &&
ctor->getResilienceExpansion() == ResilienceExpansion::Minimal) {
diagnose(ctor, diag::class_designated_init_inlineable_resilient,
ClassD->getDeclaredInterfaceType(),
diff --git a/stdlib/public/core/Policy.swift b/stdlib/public/core/Policy.swift
index 8128f8c..ce5db62 100644
--- a/stdlib/public/core/Policy.swift
+++ b/stdlib/public/core/Policy.swift
@@ -474,39 +474,44 @@
static var allZeros: Self { get }
}
-/// Calculates the union of bits sets in the two arguments and stores the result
-/// in the first argument.
-///
-/// - Parameters:
-/// - lhs: A value to update with the union of bits set in the two arguments.
-/// - rhs: Another value.
-@_inlineable // FIXME(sil-serialize-all)
-public func |= <T : _BitwiseOperations>(lhs: inout T, rhs: T) {
- lhs = lhs | rhs
-}
+extension _BitwiseOperations {
+ /// Calculates the union of bits sets in the two arguments and stores the result
+ /// in the first argument.
+ ///
+ /// - Parameters:
+ /// - lhs: A value to update with the union of bits set in the two arguments.
+ /// - rhs: Another value.
+ @_inlineable // FIXME(sil-serialize-all)
+ @available(swift, obsoleted: 4.1)
+ public static func |= (lhs: inout Self, rhs: Self) {
+ lhs = lhs | rhs
+ }
-/// Calculates the intersections of bits sets in the two arguments and stores
-/// the result in the first argument.
-///
-/// - Parameters:
-/// - lhs: A value to update with the intersections of bits set in the two
-/// arguments.
-/// - rhs: Another value.
-@_inlineable // FIXME(sil-serialize-all)
-public func &= <T : _BitwiseOperations>(lhs: inout T, rhs: T) {
- lhs = lhs & rhs
-}
+ /// Calculates the intersections of bits sets in the two arguments and stores
+ /// the result in the first argument.
+ ///
+ /// - Parameters:
+ /// - lhs: A value to update with the intersections of bits set in the two
+ /// arguments.
+ /// - rhs: Another value.
+ @_inlineable // FIXME(sil-serialize-all)
+ @available(swift, obsoleted: 4.1)
+ public static func &= (lhs: inout Self, rhs: Self) {
+ lhs = lhs & rhs
+ }
-/// Calculates the bits that are set in exactly one of the two arguments and
-/// stores the result in the first argument.
-///
-/// - Parameters:
-/// - lhs: A value to update with the bits that are set in exactly one of the
-/// two arguments.
-/// - rhs: Another value.
-@_inlineable // FIXME(sil-serialize-all)
-public func ^= <T : _BitwiseOperations>(lhs: inout T, rhs: T) {
- lhs = lhs ^ rhs
+ /// Calculates the bits that are set in exactly one of the two arguments and
+ /// stores the result in the first argument.
+ ///
+ /// - Parameters:
+ /// - lhs: A value to update with the bits that are set in exactly one of the
+ /// two arguments.
+ /// - rhs: Another value.
+ @_inlineable // FIXME(sil-serialize-all)
+ @available(swift, obsoleted: 4.1)
+ public static func ^= (lhs: inout Self, rhs: Self) {
+ lhs = lhs ^ rhs
+ }
}
//===----------------------------------------------------------------------===//
diff --git a/test/ClangImporter/Inputs/attr-objc_subclassing_restricted.h b/test/ClangImporter/Inputs/attr-objc_subclassing_restricted.h
new file mode 100644
index 0000000..acdd65b
--- /dev/null
+++ b/test/ClangImporter/Inputs/attr-objc_subclassing_restricted.h
@@ -0,0 +1,6 @@
+// This file is meant to be used with the mock SDK.
+#import <Foundation.h>
+
+__attribute__((objc_subclassing_restricted))
+@interface Restricted: NSObject
+@end
diff --git a/test/ClangImporter/attr-objc_subclassing_restricted.swift b/test/ClangImporter/attr-objc_subclassing_restricted.swift
new file mode 100644
index 0000000..dd9b4ac
--- /dev/null
+++ b/test/ClangImporter/attr-objc_subclassing_restricted.swift
@@ -0,0 +1,9 @@
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -import-objc-header %S/Inputs/attr-objc_subclassing_restricted.h %s -swift-version 5 -verify
+
+// No errors in Swift 3 and 4 modes.
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -import-objc-header %S/Inputs/attr-objc_subclassing_restricted.h %s -swift-version 4
+
+// REQUIRES: objc_interop
+
+class Sub: Restricted { // expected-error {{cannot inherit from non-open class 'Restricted' outside of its defining module}}
+}
diff --git a/test/Constraints/iuo.swift b/test/Constraints/iuo.swift
index b483b4f..a4b0731 100644
--- a/test/Constraints/iuo.swift
+++ b/test/Constraints/iuo.swift
@@ -167,3 +167,14 @@
let _: (Bool) -> T? = id(T.iuoResultStatic as (Bool) -> T?)
let _: T! = id(T.iuoResultStatic(true))
}
+
+class rdar37241550 {
+ public init(blah: Float) { fatalError() }
+ public convenience init() { fatalError() }
+ public convenience init!(with void: ()) { fatalError() }
+
+ static func f(_ fn: () -> rdar37241550) {}
+ static func test() {
+ f(rdar37241550.init) // no error, the failable init is not applicable
+ }
+}
diff --git a/test/Driver/batch_mode.swift b/test/Driver/batch_mode.swift
new file mode 100644
index 0000000..2bbf0ab
--- /dev/null
+++ b/test/Driver/batch_mode.swift
@@ -0,0 +1,64 @@
+// RUN: %empty-directory(%t)
+// RUN: touch %t/file-01.swift %t/file-02.swift %t/file-03.swift %t/file-04.swift %t/file-05.swift
+// RUN: touch %t/file-06.swift %t/file-07.swift %t/file-08.swift %t/file-09.swift %t/file-10.swift
+// RUN: touch %t/file-11.swift %t/file-12.swift %t/file-13.swift %t/file-14.swift %t/file-15.swift
+// RUN: touch %t/file-16.swift %t/file-17.swift %t/file-18.swift %t/file-19.swift %t/file-20.swift
+// RUN: touch %t/file-21.swift %t/file-22.swift %t/file-23.swift %t/file-24.swift %t/file-25.swift
+// RUN: touch %t/file-26.swift %t/file-27.swift %t/file-28.swift %t/file-29.swift %t/file-30.swift
+//
+// RUN: %swiftc_driver -enable-batch-mode -driver-show-job-lifecycle -driver-skip-execution -j 4 %t/file-01.swift %t/file-02.swift %t/file-03.swift %t/file-04.swift %t/file-05.swift %t/file-06.swift %t/file-07.swift %t/file-08.swift %t/file-09.swift %t/file-10.swift %t/file-11.swift %t/file-12.swift %t/file-13.swift %t/file-14.swift %t/file-15.swift %t/file-16.swift %t/file-17.swift %t/file-18.swift %t/file-19.swift %t/file-20.swift %t/file-21.swift %t/file-22.swift %t/file-23.swift %t/file-24.swift %t/file-25.swift %t/file-26.swift %t/file-27.swift %t/file-28.swift %t/file-29.swift %t/file-30.swift | %FileCheck %s -check-prefix=SEED0
+//
+// RUN: %swiftc_driver -enable-batch-mode -driver-show-job-lifecycle -driver-skip-execution -j 4 -driver-batch-seed 1 %t/file-01.swift %t/file-02.swift %t/file-03.swift %t/file-04.swift %t/file-05.swift %t/file-06.swift %t/file-07.swift %t/file-08.swift %t/file-09.swift %t/file-10.swift %t/file-11.swift %t/file-12.swift %t/file-13.swift %t/file-14.swift %t/file-15.swift %t/file-16.swift %t/file-17.swift %t/file-18.swift %t/file-19.swift %t/file-20.swift %t/file-21.swift %t/file-22.swift %t/file-23.swift %t/file-24.swift %t/file-25.swift %t/file-26.swift %t/file-27.swift %t/file-28.swift %t/file-29.swift %t/file-30.swift | %FileCheck %s -check-prefix=SEED1
+//
+// RUN: %swiftc_driver -enable-batch-mode -driver-show-job-lifecycle -driver-skip-execution -j 4 -driver-batch-seed 2 %t/file-01.swift %t/file-02.swift %t/file-03.swift %t/file-04.swift %t/file-05.swift %t/file-06.swift %t/file-07.swift %t/file-08.swift %t/file-09.swift %t/file-10.swift %t/file-11.swift %t/file-12.swift %t/file-13.swift %t/file-14.swift %t/file-15.swift %t/file-16.swift %t/file-17.swift %t/file-18.swift %t/file-19.swift %t/file-20.swift %t/file-21.swift %t/file-22.swift %t/file-23.swift %t/file-24.swift %t/file-25.swift %t/file-26.swift %t/file-27.swift %t/file-28.swift %t/file-29.swift %t/file-30.swift | %FileCheck %s -check-prefix=SEED2
+//
+// 30 files / 4 batches => 2 batches of 8 jobs + 2 batches of 7 jobs
+//
+// SEED0: Found 30 batchable jobs
+// SEED0: Forming into 4 batches
+// SEED0: Adding {compile: {{file-01-.*}} <= file-01.swift} to batch 0
+// SEED0: Adding {compile: {{file-02-.*}} <= file-02.swift} to batch 0
+// SEED0: Adding {compile: {{file-09-.*}} <= file-09.swift} to batch 1
+// SEED0: Adding {compile: {{file-10-.*}} <= file-10.swift} to batch 1
+// SEED0: Adding {compile: {{file-19-.*}} <= file-19.swift} to batch 2
+// SEED0: Adding {compile: {{file-20-.*}} <= file-20.swift} to batch 2
+// SEED0: Adding {compile: {{file-29-.*}} <= file-29.swift} to batch 3
+// SEED0: Adding {compile: {{file-30-.*}} <= file-30.swift} to batch 3
+// SEED0: Forming batch job from 8 constituents
+// SEED0: Forming batch job from 8 constituents
+// SEED0: Forming batch job from 7 constituents
+// SEED0: Forming batch job from 7 constituents
+// SEED0: Adding batch job to task queue: {compile: file-01{{.*}} file-02{{.*}} file-03{{.*}} ... 5 more <= file-01.swift file-02.swift file-03.swift ... 5 more}
+// SEED0: Adding batch job to task queue: {compile: file-09{{.*}} file-10{{.*}} file-11{{.*}} ... 5 more <= file-09.swift file-10.swift file-11.swift ... 5 more}
+// SEED0: Adding batch job to task queue: {compile: file-17{{.*}} file-18{{.*}} file-19{{.*}} ... 4 more <= file-17.swift file-18.swift file-19.swift ... 4 more}
+// SEED0: Adding batch job to task queue: {compile: file-24{{.*}} file-25{{.*}} file-26{{.*}} ... 4 more <= file-24.swift file-25.swift file-26.swift ... 4 more}
+//
+// SEED1: Found 30 batchable jobs
+// SEED1: Forming into 4 batches
+// SEED1: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 0
+// SEED1: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 1
+// SEED1: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 2
+// SEED1: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 3
+// SEED1: Forming batch job from 8 constituents
+// SEED1: Forming batch job from 8 constituents
+// SEED1: Forming batch job from 7 constituents
+// SEED1: Forming batch job from 7 constituents
+// SEED1-NOT: Adding batch job to task queue: {compile: file-01{{.*}} file-02{{.*}} file-03{{.*}} ... 5 more <= file-01.swift file-02.swift file-03.swift ... 5 more }
+// SEED1: Added to TaskQueue: {compile: {{.*}} <= {{file-[0-3][2-9].swift .*}}}
+// SEED1: Added to TaskQueue: {compile: {{.*}} <= {{.*}}}
+// SEED1: Added to TaskQueue: {compile: {{.*}} <= {{.*}}}
+//
+// SEED2: Found 30 batchable jobs
+// SEED2: Forming into 4 batches
+// SEED2: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 0
+// SEED2: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 1
+// SEED2: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 2
+// SEED2: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 3
+// SEED2: Forming batch job from 8 constituents
+// SEED2: Forming batch job from 8 constituents
+// SEED2: Forming batch job from 7 constituents
+// SEED2: Forming batch job from 7 constituents
+// SEED2-NOT: Adding batch job to task queue: {compile: file-01{{.*}} file-02{{.*}} file-03{{.*}} ... 5 more <= file-01.swift file-02.swift file-03.swift ... 5 more }
+// SEED2: Added to TaskQueue: {compile: {{.*}} <= {{file-[0-3][2-9].swift .*}}}
+// SEED2: Added to TaskQueue: {compile: {{.*}} <= {{.*}}}
+// SEED2: Added to TaskQueue: {compile: {{.*}} <= {{.*}}}
diff --git a/test/decl/init/resilience-cross-module.swift b/test/decl/init/resilience-cross-module.swift
new file mode 100644
index 0000000..e547759
--- /dev/null
+++ b/test/decl/init/resilience-cross-module.swift
@@ -0,0 +1,38 @@
+// RUN: %empty-directory(%t)
+
+// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../../Inputs/resilient_struct.swift
+// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_protocol.swiftmodule -module-name=resilient_protocol %S/../../Inputs/resilient_protocol.swift
+
+// RUN: %target-swift-frontend -typecheck -swift-version 4 -verify -I %t %s
+// RUN: %target-swift-frontend -typecheck -swift-version 4 -verify -enable-resilience -I %t %s
+
+// RUN: %target-swift-frontend -typecheck -swift-version 5 -verify -I %t %s
+// RUN: %target-swift-frontend -typecheck -swift-version 5 -verify -enable-resilience -I %t %s
+
+import resilient_struct
+import resilient_protocol
+
+// Size is not @_fixed_layout, so we cannot define a new designated initializer
+extension Size {
+ init(ww: Int, hh: Int) {
+ self.w = ww
+ self.h = hh // expected-error {{'let' property 'h' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
+ }
+
+ // This is OK
+ init(www: Int, hhh: Int) {
+ self.init(w: www, h: hhh)
+ }
+
+ // This is OK
+ init(other: Size) {
+ self = other
+ }
+}
+
+// Protocol extension initializers are OK too
+extension OtherResilientProtocol {
+ public init(other: Self) {
+ self = other
+ }
+}
diff --git a/test/decl/init/resilience.swift b/test/decl/init/resilience.swift
index 0133982..fba6e6d 100644
--- a/test/decl/init/resilience.swift
+++ b/test/decl/init/resilience.swift
@@ -1,34 +1,9 @@
-// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -typecheck -swift-version 4 -verify -enable-resilience %s -DRESILIENT
+// RUN: %target-swift-frontend -typecheck -swift-version 5 -verify -enable-resilience %s -DRESILIENT
-// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../../Inputs/resilient_struct.swift
-// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_protocol.swiftmodule -module-name=resilient_protocol %S/../../Inputs/resilient_protocol.swift
-
-// RUN: %target-swift-frontend -typecheck -swift-version 4 -verify -I %t %s
-// RUN: %target-swift-frontend -typecheck -swift-version 4 -verify -enable-resilience -I %t %s
-
-// RUN: %target-swift-frontend -typecheck -swift-version 5 -verify -I %t %s
-// RUN: %target-swift-frontend -typecheck -swift-version 5 -verify -enable-resilience -I %t %s
-
-import resilient_struct
-import resilient_protocol
-
-// Size is not @_fixed_layout, so we cannot define a new designated initializer
-extension Size {
- init(ww: Int, hh: Int) {
- self.w = ww
- self.h = hh // expected-error {{'let' property 'h' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
- }
-
- // This is OK
- init(www: Int, hhh: Int) {
- self.init(w: www, h: hhh)
- }
-
- // This is OK
- init(other: Size) {
- self = other
- }
-}
+// There should be no errors when run without resilience enabled.
+// RUN: %target-swift-frontend -typecheck -swift-version 4 %s
+// RUN: %target-swift-frontend -typecheck -swift-version 5 %s
// Animal is not @_fixed_layout, so we cannot define an @_inlineable
// designated initializer
@@ -86,10 +61,3 @@
self.init()
}
}
-
-// Protocol extension initializers are OK too
-extension OtherResilientProtocol {
- public init(other: Self) {
- self = other
- }
-}
diff --git a/test/stdlib/BinaryIntegerRequirements.swift b/test/stdlib/BinaryIntegerRequirements.swift
new file mode 100644
index 0000000..f3c8a25
--- /dev/null
+++ b/test/stdlib/BinaryIntegerRequirements.swift
@@ -0,0 +1,61 @@
+// RUN: %swift -swift-version 4 -typecheck -verify %s
+
+struct MyInt: FixedWidthInteger { // expected-error {{type 'MyInt' does not conform to protocol 'BinaryInteger'}}
+ typealias IntegerLiteralType = Int
+ static let isSigned = false
+ init(integerLiteral value: Int) { fatalError() }
+ init(_truncatingBits bits: UInt) { fatalError() }
+ init<T : BinaryFloatingPoint>(_ source: T) { fatalError() }
+ init?<T : BinaryFloatingPoint>(exactly source: T) { fatalError() }
+ init<T : BinaryInteger>(_ source: T) { fatalError() }
+ init?<T : BinaryInteger>(exactly source: T) { fatalError() }
+ init<T : BinaryInteger>(truncatingIfNeeded source: T) { fatalError() }
+ init<T : BinaryInteger>(clamping source: T) { fatalError() }
+
+ let words = [UInt]()
+ let _lowWord: UInt = 0
+ static var bitWidth: Int { fatalError() }
+ var trailingZeroBitCount: Int { fatalError() }
+
+ static func /=(_ lhs: inout MyInt, _ rhs: MyInt) { fatalError() }
+ static func /(_ lhs: MyInt, _ rhs: MyInt) -> MyInt { fatalError() }
+ static func %=(_ lhs: inout MyInt, _ rhs: MyInt) { fatalError() }
+ static func %(_ lhs: MyInt, _ rhs: MyInt) -> MyInt { fatalError() }
+ static func +=(_ lhs: inout MyInt, _ rhs: MyInt) { fatalError() }
+ static func +(_ lhs: MyInt, _ rhs: MyInt) -> MyInt { fatalError() }
+ static func -=(_ lhs: inout MyInt, _ rhs: MyInt) { fatalError() }
+ static func -(_ lhs: MyInt, _ rhs: MyInt) -> MyInt { fatalError() }
+ static func *=(_ lhs: inout MyInt, _ rhs: MyInt) { fatalError() }
+ static func *(_ lhs: MyInt, _ rhs: MyInt) -> MyInt { fatalError() }
+
+ static func ==(_ lhs: MyInt, _ rhs: MyInt) -> Bool { fatalError() }
+ static func <(_ lhs: MyInt, _ rhs: MyInt) -> Bool { fatalError() }
+
+ static prefix func ~ (_ x: MyInt) -> MyInt { fatalError() }
+
+ static func >><RHS: BinaryInteger>(_ lhs: MyInt, _ rhs: RHS) -> MyInt { fatalError() }
+
+ static func >>=<RHS: BinaryInteger>(_ lhs: inout MyInt, _ rhs: RHS) { fatalError() }
+ static func <<<RHS: BinaryInteger>(_ lhs: MyInt, _ rhs: RHS) -> MyInt { fatalError() }
+ static func <<=<RHS: BinaryInteger>(_ lhs: inout MyInt, _ rhs: RHS) { fatalError() }
+
+ func quotientAndRemainder(dividingBy rhs: MyInt) -> (quotient: MyInt, remainder: MyInt) { fatalError() }
+ func signum() -> MyInt { fatalError() }
+
+ var hashValue: Int { fatalError() }
+ var byteSwapped: MyInt { fatalError() }
+ static var max: MyInt { fatalError() }
+ static var min: MyInt { fatalError() }
+ func addingReportingOverflow(_ rhs: MyInt) -> (partialValue: MyInt, overflow: Bool) { fatalError() }
+ func subtractingReportingOverflow(_ rhs: MyInt) -> (partialValue: MyInt, overflow: Bool) { fatalError() }
+ func multipliedReportingOverflow(by rhs: MyInt) -> (partialValue: MyInt, overflow: Bool) { fatalError() }
+ func dividedReportingOverflow(by rhs: MyInt) -> (partialValue: MyInt, overflow: Bool) { fatalError() }
+ func remainderReportingOverflow(dividingBy rhs: MyInt) -> (partialValue: MyInt, overflow: Bool) { fatalError() }
+ func multipliedFullWidth(by other: MyInt) -> (high: MyInt, low: Magnitude) { fatalError() }
+ func dividingFullWidth(_ dividend: (high: MyInt, low: Magnitude)) -> (quotient: MyInt, remainder: MyInt) { fatalError() }
+
+ var nonzeroBitCount: Int { fatalError() }
+ var leadingZeroBitCount: Int { fatalError() }
+
+ var magnitude: UInt { fatalError() }
+}