Merge pull request #12797 from anemet/opt-remark-demangle
diff --git a/CODE_OWNERS.TXT b/CODE_OWNERS.TXT
index b6244ec..1309040 100644
--- a/CODE_OWNERS.TXT
+++ b/CODE_OWNERS.TXT
@@ -4,49 +4,85 @@
what goes in or not.
The list is sorted by surname and formatted to allow easy grepping and
-beautification by scripts. The fields are: name (N), email (E), web-address
-(W), description (D).
+beautification by scripts. The fields are: name (N), email (E),
+GitHub account (G), description (D).
N: Ben Cohen
E: ben_cohen@apple.com
+G: airspeedswift
D: Swift standard library
+N: Brian Croom
+E: bcroom@apple.com
+G: briancroom
+D: XCTest overlay
+
N: Erik Eckstein
E: eeckstein@apple.com
+G: eeckstein
D: SILOptimizer
N: Xi Ge
E: xi_ge@apple.com
+G: nkcsgexi
D: Markup, Migrator, lib/Syntax
N: Doug Gregor
E: dgregor@apple.com
+G: DougGregor
D: AST, Basic, Parse, Sema
N: Joe Groff
E: jgroff@apple.com
+G: jckarter
D: SIL, SILGen, everything in Swift not covered by someone else
N: Argyrios Kyrzidis
E: kyrtzidis@apple.com
-D: IDE, SourceKit, swift-ide-test
+G: akyrtzi
+D: IDE, Index, SourceKit, swift-ide-test
N: Luke Larson
E: llarson@apple.com
+G: lplarson
D: Swift Benchmark Suite
N: John McCall
E: rjmccall@apple.com
+G: rjmccall
D: Demangler, IRGen, Runtime
+N: Max Moiseev
+E: moiseev@apple.com
+G: moiseev
+D: Apple contact for non-corelibs overlays
+
+N: Tony Parker
+E: anthony.parker@apple.com
+G: parkera
+D: Foundation overlay
+
N: Slava Pestov
E: spestov@apple.com
+G: slavapestov
D: Reflection, SwiftRemoteMirror
+N: Adrian Prantl
+E: aprantl@apple.com
+G: adrian-prantl
+D: Debug info
+
N: Jordan Rose
E: jordan_rose@apple.com
-D: ClangImporter, Serialization, (Objective-)C printer, Driver
+G: jrose-apple
+D: ClangImporter, Serialization, PrintAsObjC, Driver, Frontend
+
+N: Daniel Steffen
+E: dsteffen@apple.com
+G: das
+D: Dispatch overlay
N: Anna Zaks
E: ganna@apple.com
-D: SIL diagnostics passes
+G: AnnaZaks
+D: SIL diagnostics passes, sanitizers
diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake
index 91e5cdb..5dd2ae9 100644
--- a/cmake/modules/AddSwift.cmake
+++ b/cmake/modules/AddSwift.cmake
@@ -719,7 +719,7 @@
# On platforms that use ELF binaries we add markers for metadata sections in
# the shared libraries using these object files. This wouldn't be necessary
# if the link was done by the swift binary: rdar://problem/19007002
- if(SWIFTLIB_TARGET_LIBRARY AND
+ if(SWIFTLIB_SINGLE_TARGET_LIBRARY AND
"${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}" STREQUAL "ELF")
if("${libkind}" STREQUAL "SHARED")
set(arch_subdir "${SWIFTLIB_DIR}/${SWIFTLIB_SINGLE_SUBDIR}")
@@ -874,7 +874,8 @@
# The section metadata objects are generated sources, and we need to tell CMake
# not to expect to find them prior to their generation.
- if("${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}" STREQUAL "ELF")
+ if(SWIFTLIB_SINGLE_TARGET_LIBRARY AND
+ "${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}" STREQUAL "ELF")
if("${libkind}" STREQUAL "SHARED")
set_source_files_properties(${SWIFT_SECTIONS_OBJECT_BEGIN} PROPERTIES GENERATED 1)
set_source_files_properties(${SWIFT_SECTIONS_OBJECT_END} PROPERTIES GENERATED 1)
diff --git a/docs/SIL.rst b/docs/SIL.rst
index a6753b4..fdcbde9 100644
--- a/docs/SIL.rst
+++ b/docs/SIL.rst
@@ -582,6 +582,43 @@
importer only imports non-native methods and types as ``throws``
when it is possible to do this automatically.
+Coroutine Types
+```````````````
+
+A coroutine is a function which can suspend itself and return control to
+its caller without terminating the function. That is, it does not need to
+obey a strict stack discipline.
+
+SIL supports two kinds of coroutine: ``@yield_many`` and ``@yield_once``.
+Either of these attributes may be written before a function type to
+indicate that it is a coroutine type.
+
+A coroutine type may declare any number of *yielded values*, which is to
+say, values which are provided to the caller at a yield point. Yielded
+values are written in the result list of a function type, prefixed by
+the ``@yields`` attribute. A yielded value may have a convention attribute,
+taken from the set of parameter attributes and interpreted as if the yield
+site were calling back to the calling function.
+
+Currently, a coroutine may not have normal results.
+
+Coroutine functions may be used in many of the same ways as normal
+function values. However, they cannot be called with the standard
+``apply`` or ``try_apply`` instructions.
+
+Coroutines may contain the special ``yield`` and ``unwind`` instructions.
+
+A ``@yield_many`` coroutine may yield as many times as it desires.
+A ``@yield_once`` coroutine may yield exactly once before returning,
+although it may also ``throw`` before reaching that point.
+
+This coroutine representation is well-suited to coroutines whose control
+flow is tightly integrated with their callers and which intend to pass
+information back and forth. This matches the needs of generalized
+accessor and generator features in Swift. It is not a particularly good
+match for ``async``/``await``-style features; a simpler representation
+would probably do fine for that.
+
Properties of Types
```````````````````
@@ -4698,6 +4735,10 @@
resumes at the normal destination, and the value of the basic block argument
will be the operand of this ``return`` instruction.
+If the current function is a ``yield_once`` coroutine, there must not be
+a path from the entry block to a ``return`` which does not pass through
+a ``yield`` instruction. This rule does not apply in the ``raw`` SIL stage.
+
``return`` does not retain or release its operand or any other values.
A function must not contain more than one ``return`` instruction.
@@ -4713,7 +4754,7 @@
Exits the current function and returns control to the calling
function. The current function must have an error result, and so the
-function must have been invoked with a ``try_apply` instruction.
+function must have been invoked with a ``try_apply`` instruction.
Control will resume in the error destination of that instruction, and
the basic block argument will be the operand of the ``throw``.
@@ -4721,6 +4762,50 @@
A function must not contain more than one ``throw`` instruction.
+yield
+`````
+::
+
+ sil-terminator ::= 'yield' sil-yield-values
+ ',' 'resume' sil-identifier
+ ',' 'unwind' sil-identifier
+ sil-yield-values ::= sil-operand
+ sil-yield-values ::= '(' (sil-operand (',' sil-operand)*)? ')'
+
+Temporarily suspends the current function and provides the given
+values to the calling function. The current function must be a coroutine,
+and the yield values must match the yield types of the coroutine.
+If the calling function resumes the coroutine normally, control passes to
+the ``resume`` destination. If the calling function aborts the coroutine,
+control passes to the ``unwind`` destination.
+
+The ``resume`` and ``unwind`` destination blocks must be uniquely
+referenced by the ``yield`` instruction. This prevents them from becoming
+critical edges.
+
+In a ``yield_once`` coroutine, there must not be a control flow path leading
+from the ``resume`` edge to another ``yield`` instruction in this function.
+This rule does not apply in the ``raw`` SIL stage.
+
+There must not be a control flow path leading from the ``unwind`` edge to
+a ``return`` instruction, to a ``throw`` instruction, or to any block
+reachable from the entry block via a path that does not pass through
+an ``unwind`` edge. That is, the blocks reachable from ``unwind`` edges
+must jointly form a disjoint subfunction of the coroutine.
+
+unwind
+``````
+::
+
+ sil-terminator ::= 'unwind'
+
+Exits the current function and returns control to the calling function,
+completing an unwind from a ``yield``. The current function must be a
+coroutine.
+
+``unwind`` is only permitted in blocks reachable from the ``unwind`` edges
+of ``yield`` instructions.
+
br
``
::
diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def
index c7629da..d9fc118 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -60,6 +60,9 @@
TYPE_ATTR(objc_metatype)
TYPE_ATTR(opened)
TYPE_ATTR(pseudogeneric)
+TYPE_ATTR(yields)
+TYPE_ATTR(yield_once)
+TYPE_ATTR(yield_many)
// SIL metatype attributes.
TYPE_ATTR(thin)
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index a832920..e64b60b 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -3183,6 +3183,8 @@
"SIL function types cannot have labeled inputs", ())
ERROR(sil_function_output_label,PointsToFirstBadToken,
"SIL function types cannot have labeled results", ())
+ERROR(sil_non_coro_yields,PointsToFirstBadToken,
+ "non-coroutine SIL function types cannot have @yield results", ())
ERROR(sil_function_repeat_convention,PointsToFirstBadToken,
"repeated %select{parameter|result|callee}0 convention attribute",
(unsigned))
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index 9e8b509..35f9411 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -802,6 +802,16 @@
/// Determine whether the two given types are in the same equivalence class.
bool areInSameEquivalenceClass(Type type1, Type type2);
+ /// Verify the correctness of the given generic signature.
+ ///
+ /// This routine will test that the given generic signature is both minimal
+ /// and canonical, emitting errors if it is not.
+ static void verifyGenericSignature(ASTContext &context,
+ GenericSignature *sig);
+
+ /// Verify all of the generic sigantures in the given module.
+ static void verifyGenericSignaturesInModule(ModuleDecl *module);
+
/// \brief Dump all of the requirements, both specified and inferred.
LLVM_ATTRIBUTE_DEPRECATED(
void dump(),
diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h
index 377b7e2..4e99b99 100644
--- a/include/swift/AST/Module.h
+++ b/include/swift/AST/Module.h
@@ -1173,6 +1173,15 @@
virtual bool isSystemModule() const { return false; }
+ /// Retrieve the set of generic signatures stored within this module.
+ ///
+ /// \returns \c true if this module file supports retrieving all of the
+ /// generic signatures, \c false otherwise.
+ virtual bool getAllGenericSignatures(
+ SmallVectorImpl<GenericSignature*> &genericSignatures) {
+ return false;
+ }
+
static bool classof(const FileUnit *file) {
return file->getKind() == FileUnitKind::SerializedAST ||
file->getKind() == FileUnitKind::ClangModule;
diff --git a/include/swift/AST/PrettyStackTrace.h b/include/swift/AST/PrettyStackTrace.h
index 96894b1..9715dd32 100644
--- a/include/swift/AST/PrettyStackTrace.h
+++ b/include/swift/AST/PrettyStackTrace.h
@@ -26,6 +26,7 @@
class ASTContext;
class Decl;
class Expr;
+ class GenericSignature;
class Pattern;
class Stmt;
class TypeRepr;
@@ -129,6 +130,24 @@
virtual void print(llvm::raw_ostream &OS) const;
};
+class PrettyStackTraceGenericSignature : public llvm::PrettyStackTraceEntry {
+ const char *Action;
+ GenericSignature *GenericSig;
+ Optional<unsigned> Requirement;
+
+public:
+ PrettyStackTraceGenericSignature(const char *action,
+ GenericSignature *genericSig,
+ Optional<unsigned> requirement = None)
+ : Action(action), GenericSig(genericSig), Requirement(requirement) { }
+
+ void setRequirement(Optional<unsigned> requirement) {
+ Requirement = requirement;
+ }
+
+ void print(llvm::raw_ostream &out) const override;
+};
+
} // end namespace swift
#endif
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index 10ca863..5663a15 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -319,8 +319,9 @@
unsigned ExtInfo : 16;
unsigned CalleeConvention : 3;
unsigned HasErrorResult : 1;
+ unsigned CoroutineKind : 2;
};
- enum { NumSILFunctionTypeBits = NumTypeBaseBits + 16+5 };
+ enum { NumSILFunctionTypeBits = NumTypeBaseBits + 16 + 6 };
static_assert(NumSILFunctionTypeBits <= 32, "fits in an unsigned");
struct AnyMetatypeTypeBitfields {
@@ -3175,6 +3176,42 @@
return !(*this == rhs);
}
};
+
+using YieldConvention = ParameterConvention;
+
+/// The type and convention of a value yielded from a yield-once or
+/// yield-many coroutine.
+class SILYieldInfo : public SILParameterInfo {
+public:
+ SILYieldInfo() {}
+ SILYieldInfo(CanType type, YieldConvention conv)
+ : SILParameterInfo(type, conv) {
+ }
+
+ SILYieldInfo getWithType(CanType type) const {
+ return SILYieldInfo(type, getConvention());
+ }
+
+ template<typename F>
+ SILYieldInfo map(const F &fn) const {
+ return getWithType(fn(getType()));
+ }
+};
+
+/// SILCoroutineKind - What kind of coroutine is this SILFunction?
+enum class SILCoroutineKind : uint8_t {
+ /// This function is not a coroutine. It may have arbitrary normal
+ /// results and may not have yield results.
+ None,
+
+ /// This function is a yield-once coroutine (used by e.g. accessors).
+ /// It must not have normal results and may have arbitrary yield results.
+ YieldOnce,
+
+ /// This function is a yield-many coroutine (used by e.g. generators).
+ /// It must not have normal results and may have arbitrary yield results.
+ YieldMany,
+};
class SILFunctionType;
typedef CanTypeWrapper<SILFunctionType> CanSILFunctionType;
@@ -3334,16 +3371,20 @@
private:
unsigned NumParameters;
- unsigned NumResults : 16; // Not including the ErrorResult.
- unsigned NumIndirectFormalResults : 16; // Subset of NumResults.
+
+ // These are *normal* results if this is not a coroutine and *yield* results
+ // otherwise.
+ unsigned NumAnyResults : 16; // Not including the ErrorResult.
+ unsigned NumAnyIndirectFormalResults : 16; // Subset of NumAnyResults.
// The layout of a SILFunctionType in memory is:
// SILFunctionType
// SILParameterInfo[NumParameters]
- // SILResultInfo[NumResults]
- // SILResultInfo? // if hasErrorResult()
- // CanType? // if NumResults > 1, formal result cache
- // CanType? // if NumResults > 1, all result cache
+ // SILResultInfo[isCoroutine() ? 0 : NumAnyResults]
+ // SILYieldInfo[isCoroutine() ? NumAnyResults : 0]
+ // SILResultInfo? // if hasErrorResult()
+ // CanType? // if !isCoro && NumAnyResults > 1, formal result cache
+ // CanType? // if !isCoro && NumAnyResults > 1, all result cache
CanGenericSignature GenericSig;
Optional<ProtocolConformanceRef> WitnessMethodConformance;
@@ -3354,48 +3395,74 @@
MutableArrayRef<SILResultInfo> getMutableResults() {
auto *ptr = reinterpret_cast<SILResultInfo *>(getMutableParameters().end());
- return MutableArrayRef<SILResultInfo>(ptr, getNumResults());
+ return {ptr, getNumResults()};
}
- SILResultInfo *getEndOfNormalResults() { return getMutableResults().end(); }
+ MutableArrayRef<SILYieldInfo> getMutableYields() {
+ auto *ptr = reinterpret_cast<SILYieldInfo *>(getMutableParameters().end());
+ return {ptr, getNumYields()};
+ }
+
+ /// Return a pointer past the end of the formal results, whether they
+ /// are yield-results or normal results.
+ void *getEndOfFormalResults() {
+ return isCoroutine() ? static_cast<void*>(getMutableYields().end())
+ : static_cast<void*>(getMutableResults().end());
+ }
SILResultInfo &getMutableErrorResult() {
assert(hasErrorResult());
- return *getEndOfNormalResults();
+ return *reinterpret_cast<SILResultInfo*>(getEndOfFormalResults());
}
- bool hasResultCache() const { return NumResults > 1; }
+ /// Return a pointer past the end of all of the results, including the
+ /// error result if one is present.
+ void *getEndOfAllResults() {
+ void *end = getEndOfFormalResults();
+ if (hasErrorResult())
+ end = reinterpret_cast<char*>(end) + sizeof(SILResultInfo);
+ return end;
+ }
+
+ /// Do we have slots for caches of the normal-result tuple type?
+ bool hasResultCache() const {
+ return NumAnyResults > 1 && !isCoroutine();
+ }
CanType &getMutableFormalResultsCache() const {
assert(hasResultCache());
- auto *ptr = const_cast<SILFunctionType *>(this)->getEndOfNormalResults()
- + size_t(hasErrorResult());
+ auto *ptr = const_cast<SILFunctionType *>(this)->getEndOfAllResults();
return *reinterpret_cast<CanType*>(ptr);
}
CanType &getMutableAllResultsCache() const {
assert(hasResultCache());
- auto *ptr = const_cast<SILFunctionType *>(this)->getEndOfNormalResults()
- + size_t(hasErrorResult());
+ auto *ptr = const_cast<SILFunctionType *>(this)->getEndOfAllResults();
return *(reinterpret_cast<CanType *>(ptr) + 1);
}
- SILFunctionType(
- GenericSignature *genericSig, ExtInfo ext,
- ParameterConvention calleeConvention, ArrayRef<SILParameterInfo> params,
- ArrayRef<SILResultInfo> normalResults,
- Optional<SILResultInfo> errorResult, const ASTContext &ctx,
- RecursiveTypeProperties properties,
- Optional<ProtocolConformanceRef> witnessMethodConformance = None);
+ SILFunctionType(GenericSignature *genericSig, ExtInfo ext,
+ SILCoroutineKind coroutineKind,
+ ParameterConvention calleeConvention,
+ ArrayRef<SILParameterInfo> params,
+ ArrayRef<SILYieldInfo> yieldResults,
+ ArrayRef<SILResultInfo> normalResults,
+ Optional<SILResultInfo> errorResult,
+ const ASTContext &ctx,
+ RecursiveTypeProperties properties,
+ Optional<ProtocolConformanceRef> witnessMethodConformance);
public:
- static CanSILFunctionType
- get(GenericSignature *genericSig, ExtInfo ext,
- ParameterConvention calleeConvention,
- ArrayRef<SILParameterInfo> interfaceParams,
- ArrayRef<SILResultInfo> interfaceResults,
- Optional<SILResultInfo> interfaceErrorResult, const ASTContext &ctx,
- Optional<ProtocolConformanceRef> witnessMethodConformance = None);
+ static CanSILFunctionType get(GenericSignature *genericSig,
+ ExtInfo ext,
+ SILCoroutineKind coroutineKind,
+ ParameterConvention calleeConvention,
+ ArrayRef<SILParameterInfo> interfaceParams,
+ ArrayRef<SILYieldInfo> interfaceYields,
+ ArrayRef<SILResultInfo> interfaceResults,
+ Optional<SILResultInfo> interfaceErrorResult,
+ const ASTContext &ctx,
+ Optional<ProtocolConformanceRef> witnessMethodConformance = None);
/// Given that this function type uses a C-language convention, return its
/// formal semantic result type.
@@ -3423,12 +3490,26 @@
return getCalleeConvention() == ParameterConvention::Direct_Guaranteed;
}
+ /// Is this some kind of coroutine?
+ bool isCoroutine() const {
+ return getCoroutineKind() != SILCoroutineKind::None;
+ }
+ SILCoroutineKind getCoroutineKind() const {
+ return SILCoroutineKind(SILFunctionTypeBits.CoroutineKind);
+ }
+
+ /// Return the array of all the yields.
+ ArrayRef<SILYieldInfo> getYields() const {
+ return const_cast<SILFunctionType *>(this)->getMutableYields();
+ }
+ unsigned getNumYields() const { return isCoroutine() ? NumAnyResults : 0; }
+
/// Return the array of all result information. This may contain inter-mingled
/// direct and indirect results.
ArrayRef<SILResultInfo> getResults() const {
return const_cast<SILFunctionType *>(this)->getMutableResults();
}
- unsigned getNumResults() const { return NumResults; }
+ unsigned getNumResults() const { return isCoroutine() ? 0 : NumAnyResults; }
/// Given that this function type has exactly one result, return it.
/// This is a common situation when working with a function with a known
@@ -3458,14 +3539,14 @@
// indirect property, not the SIL indirect property, should be consulted to
// determine whether function reabstraction is necessary.
unsigned getNumIndirectFormalResults() const {
- return NumIndirectFormalResults;
+ return isCoroutine() ? 0 : NumAnyIndirectFormalResults;
}
/// Does this function have any formally indirect results?
bool hasIndirectFormalResults() const {
return getNumIndirectFormalResults() != 0;
}
unsigned getNumDirectFormalResults() const {
- return NumResults - NumIndirectFormalResults;
+ return isCoroutine() ? 0 : NumAnyResults - NumAnyIndirectFormalResults;
}
struct IndirectFormalResultFilter {
@@ -3607,15 +3688,18 @@
LookupConformanceFn conformances);
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getGenericSignature(), getExtInfo(), getCalleeConvention(),
- getParameters(), getResults(), getOptionalErrorResult());
+ Profile(ID, getGenericSignature(), getExtInfo(), getCoroutineKind(),
+ getCalleeConvention(), getParameters(), getYields(),
+ getResults(), getOptionalErrorResult());
}
static void Profile(llvm::FoldingSetNodeID &ID,
GenericSignature *genericSig,
ExtInfo info,
+ SILCoroutineKind coroutineKind,
ParameterConvention calleeConvention,
ArrayRef<SILParameterInfo> params,
- ArrayRef<SILResultInfo> result,
+ ArrayRef<SILYieldInfo> yields,
+ ArrayRef<SILResultInfo> results,
Optional<SILResultInfo> errorResult);
// Implement isa/cast/dyncast/etc.
diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h
index 76e6733..db3c8f6 100644
--- a/include/swift/Frontend/FrontendOptions.h
+++ b/include/swift/Frontend/FrontendOptions.h
@@ -296,6 +296,9 @@
/// too complex.
unsigned SolverExpressionTimeThreshold = 0;
+ /// The module for which we should verify all of the generic signatures.
+ std::string VerifyGenericSignaturesInModule;
+
enum ActionType {
NoneAction, ///< No specific action
Parse, ///< Parse only
diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td
index 018ec22..159dbcd 100644
--- a/include/swift/Option/FrontendOptions.td
+++ b/include/swift/Option/FrontendOptions.td
@@ -76,6 +76,9 @@
HelpText<"Like -verify, but updates the original source file">;
def verify_ignore_unknown: Flag<["-"], "verify-ignore-unknown">,
HelpText<"Allow diagnostics for '<unknown>' location in verify mode">;
+def verify_generic_signatures : Separate<["-"], "verify-generic-signatures">,
+ MetaVarName<"<module-name>">,
+ HelpText<"Verify the generic signatures in the given module">;
def show_diagnostics_after_fatal : Flag<["-"], "show-diagnostics-after-fatal">,
HelpText<"Keep emitting subsequent diagnostics after a fatal error">;
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index 0fa561a..7fd371f 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -58,6 +58,7 @@
class SyntaxParsingContext;
struct RawSyntaxInfo;
struct RawTokenSyntax;
+ enum class SyntaxKind;
}// end of syntax namespace
/// Different contexts in which BraceItemList are parsed.
@@ -416,12 +417,7 @@
BacktrackingScope(Parser &P)
: P(P), PP(P.getParserPosition()), DT(P.Diags) {}
- ~BacktrackingScope() {
- if (Backtrack) {
- P.backtrackToPosition(PP);
- DT.abort();
- }
- }
+ ~BacktrackingScope();
void cancelBacktrack() {
Backtrack = false;
@@ -674,6 +670,7 @@
/// \brief Parse a comma separated list of some elements.
ParserStatus parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
bool AllowSepAfterLast, Diag<> ErrorDiag,
+ syntax::SyntaxKind Kind,
std::function<ParserStatus()> callback);
void consumeTopLevelDecl(ParserPosition BeginParserPosition,
@@ -1247,7 +1244,8 @@
SourceLoc &inLoc);
Expr *parseExprAnonClosureArg();
- ParserResult<Expr> parseExprList(tok LeftTok, tok RightTok);
+ ParserResult<Expr> parseExprList(tok LeftTok, tok RightTok,
+ syntax::SyntaxKind Kind);
/// Parse an expression list, keeping all of the pieces separated.
ParserStatus parseExprList(tok leftTok, tok rightTok,
@@ -1258,7 +1256,8 @@
SmallVectorImpl<Identifier> &exprLabels,
SmallVectorImpl<SourceLoc> &exprLabelLocs,
SourceLoc &rightLoc,
- Expr *&trailingClosure);
+ Expr *&trailingClosure,
+ syntax::SyntaxKind Kind);
ParserResult<Expr> parseTrailingClosure(SourceRange calleeRange);
diff --git a/include/swift/Reflection/ReflectionContext.h b/include/swift/Reflection/ReflectionContext.h
index 920c1d2..fd459d9 100644
--- a/include/swift/Reflection/ReflectionContext.h
+++ b/include/swift/Reflection/ReflectionContext.h
@@ -66,7 +66,7 @@
unsigned getSizeOfHeapObject() {
// This must match sizeof(HeapObject) for the target.
- return sizeof(StoredPointer) + 8;
+ return sizeof(StoredPointer) * 2;
}
void dumpAllSections(std::ostream &OS) {
@@ -483,9 +483,8 @@
case MetadataSourceKind::ClosureBinding: {
unsigned Index = cast<ClosureBindingMetadataSource>(MS)->getIndex();
- // Skip the context's isa pointer (4 or 8 bytes) and reference counts
- // (4 bytes each regardless of platform word size). This is just
- // sizeof(HeapObject) in the target.
+ // Skip the context's HeapObject header
+ // (one word each for isa pointer and reference counts).
//
// Metadata and conformance tables are stored consecutively after
// the heap object header, in the 'necessary bindings' area.
diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index 09e8629..2e1f4c5 100644
--- a/include/swift/SIL/SILBuilder.h
+++ b/include/swift/SIL/SILBuilder.h
@@ -1617,6 +1617,18 @@
new (getModule()) ThrowInst(getSILDebugLocation(Loc), errorValue));
}
+ UnwindInst *createUnwind(SILLocation loc) {
+ return insertTerminator(
+ new (getModule()) UnwindInst(getSILDebugLocation(loc)));
+ }
+
+ YieldInst *createYield(SILLocation loc, ArrayRef<SILValue> yieldedValues,
+ SILBasicBlock *resumeBB, SILBasicBlock *unwindBB) {
+ return insertTerminator(
+ YieldInst::create(getSILDebugLocation(loc), yieldedValues,
+ resumeBB, unwindBB, getFunction()));
+ }
+
CondBranchInst *
createCondBranch(SILLocation Loc, SILValue Cond, SILBasicBlock *Target1,
SILBasicBlock *Target2,
diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h
index 833719b..c4345ed 100644
--- a/include/swift/SIL/SILCloner.h
+++ b/include/swift/SIL/SILCloner.h
@@ -2118,6 +2118,27 @@
template<typename ImplClass>
void
+SILCloner<ImplClass>::visitUnwindInst(UnwindInst *Inst) {
+ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+ doPostProcess(Inst,
+ getBuilder().createUnwind(getOpLocation(Inst->getLoc())));
+}
+
+template<typename ImplClass>
+void
+SILCloner<ImplClass>::visitYieldInst(YieldInst *Inst) {
+ auto Values = getOpValueArray<8>(Inst->getYieldedValues());
+ auto ResumeBB = getOpBasicBlock(Inst->getResumeBB());
+ auto UnwindBB = getOpBasicBlock(Inst->getUnwindBB());
+
+ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+ doPostProcess(Inst,
+ getBuilder().createYield(getOpLocation(Inst->getLoc()), Values,
+ ResumeBB, UnwindBB));
+}
+
+template<typename ImplClass>
+void
SILCloner<ImplClass>::visitBranchInst(BranchInst *Inst) {
auto Args = getOpValueArray<8>(Inst->getArgs());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
diff --git a/include/swift/SIL/SILDeclRef.h b/include/swift/SIL/SILDeclRef.h
index 4f95c8a..b1bc7be 100644
--- a/include/swift/SIL/SILDeclRef.h
+++ b/include/swift/SIL/SILDeclRef.h
@@ -66,8 +66,6 @@
/// True if the entry point is natively foreign.
bool requiresForeignToNativeThunk(ValueDecl *vd);
-unsigned getNaturalUncurryLevel(ValueDecl *vd);
-
enum ForDefinition_t : bool {
NotForDefinition = false,
ForDefinition = true
@@ -304,7 +302,7 @@
void print(llvm::raw_ostream &os) const;
void dump() const;
- unsigned getUncurryLevel() const;
+ unsigned getParameterListCount() const;
ResilienceExpansion getResilienceExpansion() const {
return ResilienceExpansion(Expansion);
diff --git a/include/swift/SIL/SILFunctionConventions.h b/include/swift/SIL/SILFunctionConventions.h
index 558541e..d26e981 100644
--- a/include/swift/SIL/SILFunctionConventions.h
+++ b/include/swift/SIL/SILFunctionConventions.h
@@ -45,10 +45,14 @@
static bool isIndirectSILParam(SILParameterInfo param, bool loweredAddresses);
+ static bool isIndirectSILYield(SILYieldInfo yield, bool loweredAddresses);
+
static bool isIndirectSILResult(SILResultInfo result, bool loweredAddresses);
static SILType getSILParamType(SILParameterInfo param, bool loweredAddresses);
+ static SILType getSILYieldType(SILYieldInfo yield, bool loweredAddresses);
+
static SILType getSILResultType(SILResultInfo param, bool loweredAddresses);
public:
@@ -77,6 +81,10 @@
return isIndirectSILParam(param, loweredAddresses);
}
+ bool isSILIndirect(SILYieldInfo yield) const {
+ return isIndirectSILYield(yield, loweredAddresses);
+ }
+
bool isSILIndirect(SILResultInfo result) const {
return isIndirectSILResult(result, loweredAddresses);
}
@@ -85,6 +93,10 @@
return getSILParamType(param, loweredAddresses);
}
+ SILType getSILType(SILYieldInfo yield) const {
+ return getSILYieldType(yield, loweredAddresses);
+ }
+
SILType getSILType(SILResultInfo result) const {
return getSILResultType(result, loweredAddresses);
}
@@ -115,6 +127,10 @@
return silConv.isSILIndirect(param);
}
+ bool isSILIndirect(SILYieldInfo yield) const {
+ return silConv.isSILIndirect(yield);
+ }
+
bool isSILIndirect(SILResultInfo result) const {
return silConv.isSILIndirect(result);
}
@@ -123,6 +139,10 @@
return silConv.getSILType(param);
}
+ SILType getSILType(SILYieldInfo yield) const {
+ return silConv.getSILType(yield);
+ }
+
SILType getSILType(SILResultInfo result) const {
return silConv.getSILType(result);
}
@@ -279,6 +299,28 @@
}
//===--------------------------------------------------------------------===//
+ // SIL yield types.
+ //===--------------------------------------------------------------------===//
+
+ unsigned getNumYields() const { return funcTy->getNumYields(); }
+
+ ArrayRef<SILYieldInfo> getYields() const {
+ return funcTy->getYields();
+ }
+
+ using SILYieldTypeIter =
+ llvm::mapped_iterator<const SILYieldInfo *, SILParameterTypeFunc>;
+ using SILYieldTypeRange = IteratorRange<SILYieldTypeIter>;
+
+ SILYieldTypeRange getYieldSILTypes() const {
+ return makeIteratorRange(
+ SILYieldTypeIter(funcTy->getYields().begin(),
+ SILParameterTypeFunc(silConv)),
+ SILYieldTypeIter(funcTy->getYields().end(),
+ SILParameterTypeFunc(silConv)));
+ }
+
+ //===--------------------------------------------------------------------===//
// SILArgument API, including indirect results and parameters.
//
// The argument indices below relate to full applies in which the caller and
@@ -363,6 +405,11 @@
llvm_unreachable("covered switch isn't covered?!");
}
+inline bool SILModuleConventions::isIndirectSILYield(SILYieldInfo yield,
+ bool loweredAddresses) {
+ return isIndirectSILParam(yield, loweredAddresses);
+}
+
inline bool SILModuleConventions::isIndirectSILResult(SILResultInfo result,
bool loweredAddresses) {
switch (result.getConvention()) {
@@ -386,6 +433,11 @@
: SILType::getPrimitiveObjectType(param.getType());
}
+inline SILType SILModuleConventions::getSILYieldType(SILYieldInfo yield,
+ bool loweredAddresses) {
+ return getSILParamType(yield, loweredAddresses);
+}
+
inline SILType SILModuleConventions::getSILResultType(SILResultInfo result,
bool loweredAddresses) {
return SILModuleConventions::isIndirectSILResult(result, loweredAddresses)
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index 1ed4bcb..a7c5364 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -6242,6 +6242,84 @@
}
};
+/// UnwindInst - Continue unwinding out of this function. Currently this is
+/// only used in coroutines as the eventual terminator of the unwind edge
+/// out of a 'yield'.
+class UnwindInst
+ : public InstructionBase<SILInstructionKind::UnwindInst,
+ TermInst> {
+ friend SILBuilder;
+
+ UnwindInst(SILDebugLocation loc)
+ : InstructionBase(loc) {}
+
+public:
+ SuccessorListTy getSuccessors() {
+ // No successors.
+ return SuccessorListTy();
+ }
+
+ ArrayRef<Operand> getAllOperands() const { return {}; }
+ MutableArrayRef<Operand> getAllOperands() { return {}; }
+};
+
+/// YieldInst - Yield control temporarily to the caller of this coroutine.
+///
+/// This is a terminator because the caller can abort the coroutine,
+/// e.g. if an error is thrown and an unwind is provoked.
+class YieldInst
+ : public InstructionBase<SILInstructionKind::YieldInst,
+ TermInst> {
+ friend SILBuilder;
+
+ SILSuccessor DestBBs[2];
+
+ TailAllocatedOperandList<0> Operands;
+
+ YieldInst(SILDebugLocation loc, ArrayRef<SILValue> yieldedValues,
+ SILBasicBlock *normalBB, SILBasicBlock *unwindBB);
+
+ static YieldInst *create(SILDebugLocation loc,
+ ArrayRef<SILValue> yieldedValues,
+ SILBasicBlock *normalBB, SILBasicBlock *unwindBB,
+ SILFunction &F);
+
+public:
+ /// Return the normal resume destination of the yield, which is where the
+ /// coroutine resumes when the caller is ready to continue normally.
+ ///
+ /// This must be the unique predecessor edge of the given block.
+ ///
+ /// Control flow along every path from this block must either loop or
+ /// eventually terminate in a 'return', 'throw', or 'unreachable'
+ /// instruction. In a yield_many coroutine, control is permitted to
+ /// first reach a 'yield' instruction; this is prohibited in a
+ /// yield_once coroutine.
+ SILBasicBlock *getResumeBB() const { return DestBBs[0]; }
+
+ /// Return the 'unwind' destination of the yield, which is where the
+ /// coroutine resumes when the caller is unconditionally aborting the
+ /// coroutine.
+ ///
+ /// This must be the unique predecessor edge of the given block.
+ ///
+ /// Control flow along every path from this block must either loop or
+ /// eventually terminate in an 'unwind' or 'unreachable' instruction.
+ /// It is not permitted to reach a 'yield' instruction.
+ SILBasicBlock *getUnwindBB() const { return DestBBs[1]; }
+
+ OperandValueArrayRef getYieldedValues() const {
+ return Operands.asValueArray();
+ }
+
+ ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
+ MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
+
+ SuccessorListTy getSuccessors() {
+ return DestBBs;
+ }
+};
+
/// BranchInst - An unconditional branch.
class BranchInst
: public InstructionBase<SILInstructionKind::BranchInst,
diff --git a/include/swift/SIL/SILNodes.def b/include/swift/SIL/SILNodes.def
index 78a6318..6afe2fe 100644
--- a/include/swift/SIL/SILNodes.def
+++ b/include/swift/SIL/SILNodes.def
@@ -498,6 +498,10 @@
TermInst, None, DoesNotRelease)
TERMINATOR(ThrowInst, throw,
TermInst, None, DoesNotRelease)
+ TERMINATOR(YieldInst, yield,
+ TermInst, MayHaveSideEffects, MayRelease)
+ TERMINATOR(UnwindInst, unwind,
+ TermInst, None, DoesNotRelease)
TERMINATOR(TryApplyInst, try_apply,
TermInst, MayHaveSideEffects, MayRelease)
TERMINATOR(BranchInst, br,
diff --git a/include/swift/SILOptimizer/Utils/SCCVisitor.h b/include/swift/SILOptimizer/Utils/SCCVisitor.h
index c0f2b4f..9ea03d2 100644
--- a/include/swift/SILOptimizer/Utils/SCCVisitor.h
+++ b/include/swift/SILOptimizer/Utils/SCCVisitor.h
@@ -133,8 +133,14 @@
case TermKind::ReturnInst:
case TermKind::SwitchValueInst:
case TermKind::ThrowInst:
+ case TermKind::UnwindInst:
llvm_unreachable("Did not expect terminator that does not have args!");
+ case TermKind::YieldInst:
+ for (auto &O : cast<YieldInst>(Term)->getAllOperands())
+ Operands.push_back(O.get());
+ return;
+
case TermKind::TryApplyInst:
for (auto &O : cast<TryApplyInst>(Term)->getAllOperands())
Operands.push_back(O.get());
diff --git a/include/swift/Serialization/DeclTypeRecordNodes.def b/include/swift/Serialization/DeclTypeRecordNodes.def
index 03f68a3..b772124 100644
--- a/include/swift/Serialization/DeclTypeRecordNodes.def
+++ b/include/swift/Serialization/DeclTypeRecordNodes.def
@@ -162,7 +162,7 @@
TRAILING_INFO(GENERIC_PARAM)
TRAILING_INFO(GENERIC_REQUIREMENT)
TRAILING_INFO(LAYOUT_REQUIREMENT)
-OTHER(GENERIC_ENVIRONMENT, 244)
+OTHER(GENERIC_SIGNATURE, 244)
OTHER(SIL_GENERIC_ENVIRONMENT, 245)
OTHER(LOCAL_DISCRIMINATOR, 248)
diff --git a/include/swift/Serialization/ModuleFile.h b/include/swift/Serialization/ModuleFile.h
index 8cc53e2..f701536 100644
--- a/include/swift/Serialization/ModuleFile.h
+++ b/include/swift/Serialization/ModuleFile.h
@@ -299,6 +299,9 @@
/// Types referenced by this module.
std::vector<Serialized<Type>> Types;
+ /// Generic signatures referenced by this module.
+ std::vector<Serialized<GenericSignature *>> GenericSignatures;
+
/// Generic environments referenced by this module.
std::vector<Serialized<GenericEnvironment *>> GenericEnvironments;
@@ -818,6 +821,9 @@
/// is loaded instead.
ModuleDecl *getModule(ArrayRef<Identifier> name);
+ /// Returns the generic signature for the given ID.
+ GenericSignature *getGenericSignature(serialization::GenericSignatureID ID);
+
/// Returns the generic signature or environment for the given ID,
/// deserializing it if needed.
///
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 746988f..bff02ca 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -54,7 +54,7 @@
/// in source control, you should also update the comment to briefly
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
-const uint16_t VERSION_MINOR = 380; // Last change: IUO decl attribute
+const uint16_t VERSION_MINOR = 381; // Last change: generic signature
using DeclIDField = BCFixed<31>;
@@ -77,6 +77,11 @@
using NormalConformanceID = DeclID;
using NormalConformanceIDField = DeclIDField;
+// GenericSignatureID must be the same as DeclID because it is stored in the
+// same way.
+using GenericSignatureID = DeclID;
+using GenericSignatureIDField = DeclIDField;
+
// GenericEnvironmentID must be the same as DeclID because it is stored in the
// same way.
using GenericEnvironmentID = DeclID;
@@ -156,6 +161,15 @@
// These IDs must \em not be renumbered or reordered without incrementing
// VERSION_MAJOR.
+enum class SILCoroutineKind : uint8_t {
+ None = 0,
+ YieldOnce = 1,
+ YieldMany = 2,
+};
+using SILCoroutineKindField = BCFixed<2>;
+
+// These IDs must \em not be renumbered or reordered without incrementing
+// VERSION_MAJOR.
enum OperatorKind : uint8_t {
Infix = 0,
Prefix,
@@ -729,25 +743,25 @@
TypeIDField, // output
FunctionTypeRepresentationField, // representation
BCFixed<1>, // throws?
- BCArray<TypeIDField> // generic parameters
- // followed by requirements
+ GenericSignatureIDField // generic signture
>;
using SILFunctionTypeLayout = BCRecordLayout<
SIL_FUNCTION_TYPE,
+ SILCoroutineKindField, // coroutine kind
ParameterConventionField, // callee convention
SILFunctionTypeRepresentationField, // representation
BCFixed<1>, // pseudogeneric?
BCFixed<1>, // noescape?
BCFixed<1>, // error result?
BCFixed<30>, // number of parameters
+ BCFixed<30>, // number of yields
BCFixed<30>, // number of results
+ GenericSignatureIDField, // generic signature
BCArray<TypeIDField> // parameter types/conventions, alternating
// followed by result types/conventions, alternating
// followed by error result type/convention
- // followed by generic parameter types
// Optionally a protocol conformance (for witness_methods)
- // Trailed by its generic requirements, if any.
>;
using SILBlockStorageTypeLayout = BCRecordLayout<
@@ -757,10 +771,9 @@
using SILLayoutLayout = BCRecordLayout<
SIL_LAYOUT,
+ GenericSignatureIDField, // generic signature
BCFixed<31>, // number of fields
BCArray<TypeIDWithBitField> // field types with mutability
- // followed by generic parameters
- // trailed by generic requirements, if any
>;
using SILBoxTypeLayout = BCRecordLayout<
@@ -1154,9 +1167,9 @@
DeclIDField // Typealias
>;
- using GenericEnvironmentLayout = BCRecordLayout<
- GENERIC_ENVIRONMENT,
- BCArray<TypeIDField> // sugared interface types
+ using GenericSignatureLayout = BCRecordLayout<
+ GENERIC_SIGNATURE,
+ BCArray<TypeIDField> // generic parameter types
>;
using SILGenericEnvironmentLayout = BCRecordLayout<
@@ -1271,8 +1284,8 @@
using XRefExtensionPathPieceLayout = BCRecordLayout<
XREF_EXTENSION_PATH_PIECE,
ModuleIDField, // module ID
- BCArray<TypeIDField> // for a constrained extension, the type parameters
- // for a constrained extension, requirements follow
+ GenericSignatureIDField // for a constrained extension,
+ // the generic signature
>;
using XRefOperatorOrAccessorPathPieceLayout = BCRecordLayout<
@@ -1524,7 +1537,8 @@
NESTED_TYPE_DECLS,
DECL_MEMBER_NAMES,
- LastRecordKind = DECL_MEMBER_NAMES,
+ GENERIC_SIGNATURE_OFFSETS,
+ LastRecordKind = GENERIC_SIGNATURE_OFFSETS,
};
constexpr const unsigned RecordIDFieldWidth = 5;
diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h
index 0978e16..13db711 100644
--- a/include/swift/Serialization/SerializedModuleLoader.h
+++ b/include/swift/Serialization/SerializedModuleLoader.h
@@ -195,6 +195,10 @@
virtual const clang::Module *getUnderlyingClangModule() const override;
+ virtual bool getAllGenericSignatures(
+ SmallVectorImpl<GenericSignature*> &genericSignatures)
+ override;
+
static bool classof(const FileUnit *file) {
return file->getKind() == FileUnitKind::SerializedAST;
}
diff --git a/include/swift/Syntax/SyntaxFactory.h.gyb b/include/swift/Syntax/SyntaxFactory.h.gyb
index 26f4879..08f8372 100644
--- a/include/swift/Syntax/SyntaxFactory.h.gyb
+++ b/include/swift/Syntax/SyntaxFactory.h.gyb
@@ -56,6 +56,9 @@
static SyntaxKind getUnknownKind(SyntaxKind Kind);
+ static Syntax
+ makeBlankCollectionSyntax(SyntaxKind Kind);
+
% for node in SYNTAX_NODES:
% if node.children:
% child_params = []
diff --git a/include/swift/Syntax/SyntaxParsingContext.h b/include/swift/Syntax/SyntaxParsingContext.h
index 002f9b0..372ab45 100644
--- a/include/swift/Syntax/SyntaxParsingContext.h
+++ b/include/swift/Syntax/SyntaxParsingContext.h
@@ -37,6 +37,12 @@
/// Start and end location of this syntax node.
SourceRange SyntaxRange;
+ /// This location must be valid if this node is an implicit node, e.g.
+ /// an empty statement list collection.
+ /// This location indicates the implicit node should appear before the token
+ /// on the location.
+ SourceLoc BeforeLoc;
+
/// The raw node.
RC<RawSyntax> RawNode;
RawSyntaxInfo(RC<RawSyntax> RawNode): RawNode(RawNode) {}
@@ -57,6 +63,10 @@
return RC<RawSyntaxNode>(cast<RawSyntaxNode>(RawNode));
}
void brigeWithContext(SyntaxContextKind Kind);
+ void setBeforeLoc(SourceLoc Loc) {
+ assert(isImplicit());
+ BeforeLoc = Loc;
+ }
};
enum class SyntaxParsingContextKind: uint8_t {
@@ -75,16 +85,11 @@
ContextInfo &ContextData;
const Token &Tok;
- // Add a token syntax at the given source location to the context; this
- // token node can be used to build more complex syntax nodes in later call
- // back.
- virtual void addTokenSyntax(SourceLoc Loc) = 0;
-
// Get the context kind.
virtual SyntaxParsingContextKind getKind() = 0;
// Create a syntax node of the given kind.
- virtual void makeNode(SyntaxKind Kind) = 0;
+ virtual void makeNode(SyntaxKind Kind, SourceLoc LastTokLoc) = 0;
virtual ~SyntaxParsingContext();
// Disable the building of syntax tree in the current context.
@@ -100,8 +105,7 @@
SyntaxParsingContextRoot(SourceFile &File, unsigned BufferID, Token &Tok):
SyntaxParsingContext(File, BufferID, Tok), File(File) {}
~SyntaxParsingContextRoot();
- void addTokenSyntax(SourceLoc Loc) override {};
- void makeNode(SyntaxKind Kind) override {};
+ void makeNode(SyntaxKind Kind, SourceLoc LastTokLoc) override {};
SyntaxParsingContextKind getKind() override {
return SyntaxParsingContextKind::Root;
};
@@ -130,8 +134,7 @@
None, KnownSyntax) {};
~SyntaxParsingContextChild();
- void makeNode(SyntaxKind Kind) override;
- void addTokenSyntax(SourceLoc Loc) override;
+ void makeNode(SyntaxKind Kind, SourceLoc LastTokLoc) override;
SyntaxParsingContext* getParent() { return Parent; }
SyntaxParsingContextRoot &getRoot();
SyntaxParsingContextKind getKind() override {
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 314321f..e57bd64 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -3787,16 +3787,22 @@
void SILFunctionType::Profile(llvm::FoldingSetNodeID &id,
GenericSignature *genericParams,
ExtInfo info,
+ SILCoroutineKind coroutineKind,
ParameterConvention calleeConvention,
ArrayRef<SILParameterInfo> params,
+ ArrayRef<SILYieldInfo> yields,
ArrayRef<SILResultInfo> results,
Optional<SILResultInfo> errorResult) {
id.AddPointer(genericParams);
id.AddInteger(info.getFuncAttrKey());
+ id.AddInteger(unsigned(coroutineKind));
id.AddInteger(unsigned(calleeConvention));
id.AddInteger(params.size());
for (auto param : params)
param.profile(id);
+ id.AddInteger(yields.size());
+ for (auto yield : yields)
+ yield.profile(id);
id.AddInteger(results.size());
for (auto result : results)
result.profile(id);
@@ -3806,32 +3812,47 @@
if (errorResult) errorResult->profile(id);
}
-SILFunctionType::SILFunctionType(
- GenericSignature *genericSig, ExtInfo ext,
- ParameterConvention calleeConvention, ArrayRef<SILParameterInfo> params,
- ArrayRef<SILResultInfo> normalResults, Optional<SILResultInfo> errorResult,
- const ASTContext &ctx, RecursiveTypeProperties properties,
- Optional<ProtocolConformanceRef> witnessMethodConformance)
- : TypeBase(TypeKind::SILFunction, &ctx, properties), GenericSig(genericSig),
+SILFunctionType::SILFunctionType(GenericSignature *genericSig, ExtInfo ext,
+ SILCoroutineKind coroutineKind,
+ ParameterConvention calleeConvention,
+ ArrayRef<SILParameterInfo> params,
+ ArrayRef<SILYieldInfo> yields,
+ ArrayRef<SILResultInfo> normalResults,
+ Optional<SILResultInfo> errorResult,
+ const ASTContext &ctx,
+ RecursiveTypeProperties properties,
+ Optional<ProtocolConformanceRef> witnessMethodConformance)
+ : TypeBase(TypeKind::SILFunction, &ctx, properties),
+ GenericSig(genericSig),
WitnessMethodConformance(witnessMethodConformance) {
SILFunctionTypeBits.HasErrorResult = errorResult.hasValue();
SILFunctionTypeBits.ExtInfo = ext.Bits;
+ SILFunctionTypeBits.CoroutineKind = unsigned(coroutineKind);
NumParameters = params.size();
- NumResults = normalResults.size();
- NumIndirectFormalResults =
+ if (coroutineKind == SILCoroutineKind::None) {
+ assert(yields.empty());
+ NumAnyResults = normalResults.size();
+ NumAnyIndirectFormalResults =
std::count_if(normalResults.begin(), normalResults.end(),
[](const SILResultInfo &resultInfo) {
return resultInfo.isFormalIndirect();
});
+ memcpy(getMutableResults().data(), normalResults.data(),
+ normalResults.size() * sizeof(SILResultInfo));
+ } else {
+ assert(normalResults.empty());
+ NumAnyResults = yields.size();
+ NumAnyIndirectFormalResults = 0; // unused
+ memcpy(getMutableYields().data(), yields.data(),
+ yields.size() * sizeof(SILYieldInfo));
+ }
assert(!isIndirectFormalParameter(calleeConvention));
SILFunctionTypeBits.CalleeConvention = unsigned(calleeConvention);
memcpy(getMutableParameters().data(), params.data(),
params.size() * sizeof(SILParameterInfo));
- memcpy(getMutableResults().data(), normalResults.data(),
- normalResults.size() * sizeof(SILResultInfo));
if (errorResult)
getMutableErrorResult() = *errorResult;
@@ -3868,6 +3889,13 @@
assert(!result.getType()->hasArchetype()
&& "interface type of result should not contain context archetypes");
}
+ for (auto yield : getYields()) {
+ (void)yield;
+ assert(!yield.getType()->hasError()
+ && "interface type of yield should not contain error types");
+ assert(!yield.getType()->hasArchetype()
+ && "interface type of yield should not contain context archetypes");
+ }
if (hasErrorResult()) {
assert(!getErrorResult().getType()->hasError()
&& "interface type of result should not contain error types");
@@ -3892,14 +3920,22 @@
return CanSILBlockStorageType(storageTy);
}
-CanSILFunctionType SILFunctionType::get(
- GenericSignature *genericSig, ExtInfo ext, ParameterConvention callee,
- ArrayRef<SILParameterInfo> params, ArrayRef<SILResultInfo> normalResults,
- Optional<SILResultInfo> errorResult, const ASTContext &ctx,
- Optional<ProtocolConformanceRef> witnessMethodConformance) {
+CanSILFunctionType SILFunctionType::get(GenericSignature *genericSig,
+ ExtInfo ext,
+ SILCoroutineKind coroutineKind,
+ ParameterConvention callee,
+ ArrayRef<SILParameterInfo> params,
+ ArrayRef<SILYieldInfo> yields,
+ ArrayRef<SILResultInfo> normalResults,
+ Optional<SILResultInfo> errorResult,
+ const ASTContext &ctx,
+ Optional<ProtocolConformanceRef> witnessMethodConformance) {
+ assert(coroutineKind == SILCoroutineKind::None || normalResults.empty());
+ assert(coroutineKind != SILCoroutineKind::None || yields.empty());
+
llvm::FoldingSetNodeID id;
- SILFunctionType::Profile(id, genericSig, ext, callee, params, normalResults,
- errorResult);
+ SILFunctionType::Profile(id, genericSig, ext, coroutineKind, callee,
+ params, yields, normalResults, errorResult);
// Do we already have this generic function type?
void *insertPos;
@@ -3912,6 +3948,7 @@
// Allocate storage for the object.
size_t bytes = sizeof(SILFunctionType)
+ sizeof(SILParameterInfo) * params.size()
+ + sizeof(SILYieldInfo) * yields.size()
+ sizeof(SILResultInfo) * normalResults.size()
+ (errorResult ? sizeof(SILResultInfo) : 0)
+ (normalResults.size() > 1 ? sizeof(CanType) * 2 : 0);
@@ -3922,6 +3959,8 @@
"revisit this if you add new recursive type properties");
for (auto ¶m : params)
properties |= param.getType()->getRecursiveProperties();
+ for (auto &yield : yields)
+ properties |= yield.getType()->getRecursiveProperties();
for (auto &result : normalResults)
properties |= result.getType()->getRecursiveProperties();
if (errorResult)
@@ -3934,9 +3973,10 @@
properties.removeHasDependentMember();
}
- auto fnType = new (mem)
- SILFunctionType(genericSig, ext, callee, params, normalResults,
- errorResult, ctx, properties, witnessMethodConformance);
+ auto fnType =
+ new (mem) SILFunctionType(genericSig, ext, coroutineKind, callee,
+ params, yields, normalResults, errorResult,
+ ctx, properties, witnessMethodConformance);
ctx.Impl.SILFunctionTypes.InsertNode(fnType, insertPos);
return CanSILFunctionType(fnType);
}
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index 6a8cebf..6cad624 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -3630,6 +3630,20 @@
Printer.printStructurePost(PrintStructureKind::FunctionReturnType);
}
+ void printSILCoroutineKind(SILCoroutineKind kind) {
+ switch (kind) {
+ case SILCoroutineKind::None:
+ return;
+ case SILCoroutineKind::YieldOnce:
+ Printer << "@yield_once ";
+ return;
+ case SILCoroutineKind::YieldMany:
+ Printer << "@yield_many ";
+ return;
+ }
+ llvm_unreachable("bad convention");
+ }
+
void printCalleeConvention(ParameterConvention conv) {
switch (conv) {
case ParameterConvention::Direct_Unowned:
@@ -3651,6 +3665,7 @@
}
void visitSILFunctionType(SILFunctionType *T) {
+ printSILCoroutineKind(T->getCoroutineKind());
printFunctionExtInfo(T->getExtInfo(),
T->getWitnessMethodConformanceOrNone());
printCalleeConvention(T->getCalleeConvention());
@@ -3669,11 +3684,19 @@
}
Printer << ") -> ";
- unsigned totalResults = T->getNumResults() + unsigned(T->hasErrorResult());
+ unsigned totalResults =
+ T->getNumYields() + T->getNumResults() + unsigned(T->hasErrorResult());
if (totalResults != 1) Printer << "(";
first = true;
+
+ for (auto yield : T->getYields()) {
+ Printer.printSeparator(first, ", ");
+ Printer << "@yields ";
+ yield.print(Printer, Options);
+ }
+
for (auto result : T->getResults()) {
Printer.printSeparator(first, ", ");
result.print(Printer, Options);
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index 2b31ca1..4279839 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -20,6 +20,7 @@
#include "swift/AST/Decl.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Module.h"
+#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/Types.h"
#include "swift/Basic/STLExtras.h"
#include <functional>
@@ -174,6 +175,18 @@
return getCanonicalSignature() == this;
}
+#ifndef NDEBUG
+/// Determine the canonical ordering of requirements.
+static unsigned getRequirementKindOrder(RequirementKind kind) {
+ switch (kind) {
+ case RequirementKind::Conformance: return 2;
+ case RequirementKind::Superclass: return 0;
+ case RequirementKind::SameType: return 3;
+ case RequirementKind::Layout: return 1;
+ }
+}
+#endif
+
CanGenericSignature GenericSignature::getCanonical(
ArrayRef<GenericTypeParamType *> params,
ArrayRef<Requirement> requirements) {
@@ -197,8 +210,105 @@
Requirement(reqt.getKind(), reqt.getFirstType()->getCanonicalType(),
reqt.getLayoutConstraint()));
}
+
auto canSig = get(canonicalParams, canonicalRequirements,
/*isKnownCanonical=*/true);
+
+#ifndef NDEBUG
+ PrettyStackTraceGenericSignature debugStack("canonicalizing", canSig);
+
+ // Check that the signature is canonical.
+ for (unsigned idx : indices(canonicalRequirements)) {
+ debugStack.setRequirement(idx);
+
+ const auto &reqt = canonicalRequirements[idx];
+
+ // Left-hand side must be canonical in its context.
+ // Check canonicalization of requirement itself.
+ switch (reqt.getKind()) {
+ case RequirementKind::Superclass:
+ assert(canSig->isCanonicalTypeInContext(reqt.getFirstType()) &&
+ "Left-hand side is not canonical");
+ assert(canSig->isCanonicalTypeInContext(reqt.getSecondType()) &&
+ "Superclass type isn't canonical in its own context");
+ break;
+
+ case RequirementKind::Layout:
+ assert(canSig->isCanonicalTypeInContext(reqt.getFirstType()) &&
+ "Left-hand side is not canonical");
+ break;
+
+ case RequirementKind::SameType:
+ assert(reqt.getFirstType()->isTypeParameter() &&
+ "Left-hand side must be a type parameter");
+ if (reqt.getSecondType()->isTypeParameter()) {
+ assert(compareDependentTypes(reqt.getFirstType(), reqt.getSecondType())
+ < 0 &&
+ "Out-of-order type parameters in same-type constraint");
+ } else {
+ assert(canSig->isCanonicalTypeInContext(reqt.getSecondType()) &&
+ "Concrete same-type isn't canonical in its own context");
+ }
+ break;
+
+ case RequirementKind::Conformance:
+ assert(reqt.getFirstType()->isTypeParameter() &&
+ "Left-hand side must be a type parameter");
+ assert(isa<ProtocolType>(reqt.getSecondType().getPointer()) &&
+ "Right-hand side of conformance isn't a protocol type");
+ break;
+ }
+
+ // From here on, we're only interested in requirements beyond the first.
+ if (idx == 0) continue;
+
+ // Make sure that the left-hand sides are in nondecreasing order.
+ const auto &prevReqt = canonicalRequirements[idx-1];
+ int compareLHS =
+ compareDependentTypes(prevReqt.getFirstType(), reqt.getFirstType());
+ assert(compareLHS <= 0 && "Out-of-order left-hand sides");
+
+ // If we have two same-type requirements where the left-hand sides differ
+ // but fall into the same equivalence class, we can check the form.
+ if (compareLHS < 0 && reqt.getKind() == RequirementKind::SameType &&
+ prevReqt.getKind() == RequirementKind::SameType &&
+ canSig->areSameTypeParameterInContext(prevReqt.getFirstType(),
+ reqt.getFirstType())) {
+ // If it's a it's a type parameter, make sure the equivalence class is
+ // wired together sanely.
+ if (prevReqt.getSecondType()->isTypeParameter()) {
+ assert(prevReqt.getSecondType()->isEqual(reqt.getFirstType()) &&
+ "same-type constraints within an equiv. class are out-of-order");
+ } else {
+ // Otherwise, the concrete types must match up.
+ assert(prevReqt.getSecondType()->isEqual(reqt.getSecondType()) &&
+ "inconsistent concrete same-type constraints in equiv. class");
+ }
+ }
+
+ // From here on, we only care about cases where the previous and current
+ // requirements have the same left-hand side.
+ if (compareLHS != 0) continue;
+
+ // Check ordering of requirement kinds.
+ assert((getRequirementKindOrder(prevReqt.getKind()) <=
+ getRequirementKindOrder(reqt.getKind())) &&
+ "Requirements for a given kind are out-of-order");
+
+ // From here on, we only care about the same requirement kind.
+ if (prevReqt.getKind() != reqt.getKind()) continue;
+
+ assert(reqt.getKind() == RequirementKind::Conformance &&
+ "Only conformance requirements can have multiples");
+
+ auto prevProto =
+ prevReqt.getSecondType()->castTo<ProtocolType>()->getDecl();
+ auto proto = reqt.getSecondType()->castTo<ProtocolType>()->getDecl();
+ assert(ProtocolType::compareProtocols(&prevProto, &proto) < 0 &&
+ "Out-of-order conformance requirements");
+ }
+#endif
+
return CanGenericSignature(canSig);
}
@@ -621,14 +731,12 @@
type1,
ArchetypeResolutionKind::CompleteWellFormed);
assert(equivClass1 && "not a valid dependent type of this signature?");
- assert(!equivClass1->concreteType);
auto equivClass2 =
builder.resolveEquivalenceClass(
type2,
ArchetypeResolutionKind::CompleteWellFormed);
assert(equivClass2 && "not a valid dependent type of this signature?");
- assert(!equivClass2->concreteType);
return equivClass1 == equivClass2;
}
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index 4aada77..f0d7135 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -25,6 +25,7 @@
#include "swift/AST/LazyResolver.h"
#include "swift/AST/Module.h"
#include "swift/AST/ParameterList.h"
+#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/TypeMatcher.h"
#include "swift/AST/TypeRepr.h"
@@ -2954,36 +2955,30 @@
/// Resolve any unresolved dependent member types using the given builder.
static Type resolveDependentMemberTypes(GenericSignatureBuilder &builder,
- Type type,
- ArchetypeResolutionKind kind) {
+ Type type) {
if (!type->hasTypeParameter()) return type;
- return type.transformRec([&builder,kind](TypeBase *type) -> Optional<Type> {
- if (auto depTy = dyn_cast<DependentMemberType>(type)) {
- if (depTy->getAssocType()) return None;
+ return type.transformRec([&builder](TypeBase *type) -> Optional<Type> {
+ if (!type->isTypeParameter())
+ return None;
- Type newBase =
- resolveDependentMemberTypes(builder, depTy->getBase(), kind);
- if (newBase->is<ErrorType>())
- return ErrorType::get(depTy);
+ // Map the type parameter to an equivalence class.
+ auto equivClass =
+ builder.resolveEquivalenceClass(Type(type),
+ ArchetypeResolutionKind::WellFormed);
+ if (!equivClass)
+ return ErrorType::get(Type(type));
- auto parentEquivClass = builder.resolveEquivalenceClass(newBase, kind);
- if (!parentEquivClass)
- return ErrorType::get(depTy);
+ // If there is a concrete type in this equivalence class, use that.
+ if (equivClass->concreteType) {
+ // .. unless it's recursive.
+ if (equivClass->recursiveConcreteType)
+ return ErrorType::get(Type(type));
- auto memberType =
- parentEquivClass->lookupNestedType(builder, depTy->getName());
- if (!memberType)
- return ErrorType::get(depTy);
-
- if (auto assocType = dyn_cast<AssociatedTypeDecl>(memberType))
- return Type(DependentMemberType::get(newBase, assocType));
-
- // FIXME: Need to substitute here.
- return Type(type);
+ return resolveDependentMemberTypes(builder, equivClass->concreteType);
}
- return None;
+ return equivClass->getAnchor(builder, builder.getGenericParams());
});
}
@@ -3094,9 +3089,7 @@
// FIXME: Generic typealiases contradict the assumption above.
// If there is a type parameter somewhere in this type, resolve it.
if (type->hasTypeParameter()) {
- Type resolved =
- resolveDependentMemberTypes(*this, type,
- ArchetypeResolutionKind::WellFormed);
+ Type resolved = resolveDependentMemberTypes(*this, type);
if (resolved->hasError() && !type->hasError())
return ResolvedType::forUnresolved(nullptr);
@@ -5951,10 +5944,9 @@
diag::redundant_same_type_to_concrete,
diag::same_type_redundancy_here);
- // Resolve any this-far-unresolved dependent types.
+ // Resolve any thus-far-unresolved dependent types.
equivClass->concreteType =
- resolveDependentMemberTypes(*this, equivClass->concreteType,
- ArchetypeResolutionKind::CompleteWellFormed);
+ resolveDependentMemberTypes(*this, equivClass->concreteType);
}
void GenericSignatureBuilder::checkSuperclassConstraints(
@@ -5996,8 +5988,7 @@
// Resolve any this-far-unresolved dependent types.
equivClass->superclass =
- resolveDependentMemberTypes(*this, equivClass->superclass,
- ArchetypeResolutionKind::CompleteWellFormed);
+ resolveDependentMemberTypes(*this, equivClass->superclass);
// If we have a concrete type, check it.
// FIXME: Substitute into the concrete type.
@@ -6374,7 +6365,7 @@
// over-minimizing.
if (allowBuilderToMove && !Impl->HadAnyError &&
!Impl->HadAnyRedundantConstraints) {
- // Register this generic signature builer as the canonical builder for the
+ // Register this generic signature builder as the canonical builder for the
// given signature.
Context.registerGenericSignatureBuilder(sig, std::move(*this));
}
@@ -6412,3 +6403,77 @@
/*allowBuilderToMove=*/false);
}
+#pragma mark Generic signature verification
+
+void GenericSignatureBuilder::verifyGenericSignature(ASTContext &context,
+ GenericSignature *sig) {
+ llvm::errs() << "Validating generic signature: ";
+ sig->print(llvm::errs());
+ llvm::errs() << "\n";
+
+ // Try removing each requirement in turn.
+ auto genericParams = sig->getGenericParams();
+ auto requirements = sig->getRequirements();
+ for (unsigned victimIndex : indices(requirements)) {
+ PrettyStackTraceGenericSignature debugStack("verifying", sig, victimIndex);
+
+ // Form a new generic signature builder.
+ GenericSignatureBuilder builder(context);
+
+ // Add the generic parameters.
+ for (auto gp : genericParams)
+ builder.addGenericParameter(gp);
+
+ // Add the requirements *except* the victim.
+ auto source = FloatingRequirementSource::forAbstract();
+ for (unsigned i : indices(requirements)) {
+ if (i != victimIndex)
+ builder.addRequirement(requirements[i], source, nullptr);
+ }
+
+ // Finalize the generic signature. If there were any errors, we formed
+ // an invalid signature, so just continue.
+ if (builder.Impl->HadAnyError) continue;
+
+ // Form a generic signature from the result.
+ auto newSig =
+ std::move(builder).computeGenericSignature(
+ SourceLoc(),
+ /*allowConcreteGenericParams=*/true,
+ /*allowBuilderToMove=*/true);
+
+ // Check whether the removed requirement
+ assert(!newSig->isRequirementSatisfied(requirements[victimIndex]) &&
+ "Generic signature is not minimal");
+
+ // Canonicalize the signature to check that it is canonical.
+ (void)newSig->getCanonicalSignature();
+ }
+}
+
+void GenericSignatureBuilder::verifyGenericSignaturesInModule(
+ ModuleDecl *module) {
+ LoadedFile *loadedFile = nullptr;
+ for (auto fileUnit : module->getFiles()) {
+ loadedFile = dyn_cast<LoadedFile>(fileUnit);
+ if (loadedFile) break;
+ }
+
+ if (!loadedFile) return;
+
+ // Check all of the (canonical) generic signatures.
+ SmallVector<GenericSignature *, 8> allGenericSignatures;
+ SmallPtrSet<CanGenericSignature, 4> knownGenericSignatures;
+ (void)loadedFile->getAllGenericSignatures(allGenericSignatures);
+ ASTContext &context = module->getASTContext();
+ for (auto genericSig : allGenericSignatures) {
+ // Check whether this is the first time we've checked this (canonical)
+ // signature.
+ auto canGenericSig = genericSig->getCanonicalSignature();
+ if (!knownGenericSignatures.insert(canGenericSig).second) continue;
+
+ verifyGenericSignature(context, canGenericSig);
+ }
+}
+
+
diff --git a/lib/AST/PrettyStackTrace.cpp b/lib/AST/PrettyStackTrace.cpp
index 26a1fb5..649baea 100644
--- a/lib/AST/PrettyStackTrace.cpp
+++ b/lib/AST/PrettyStackTrace.cpp
@@ -18,6 +18,7 @@
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
+#include "swift/AST/GenericSignature.h"
#include "swift/AST/Module.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/Stmt.h"
@@ -214,3 +215,12 @@
out << "While " << Action << " starting at ";
printSourceLocDescription(out, Loc, Context);
}
+
+void PrettyStackTraceGenericSignature::print(llvm::raw_ostream &out) const {
+ out << "While " << Action << " generic signature ";
+ GenericSig->print(out);
+ if (Requirement) {
+ out << " in requirement #" << *Requirement;
+ }
+ out << '\n';
+}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index d1291d5..1a15a3f 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -18,6 +18,7 @@
#include "ForeignRepresentationInfo.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ExistentialLayout.h"
+#include "swift/AST/GenericSignatureBuilder.h"
#include "swift/AST/TypeVisitor.h"
#include "swift/AST/TypeWalker.h"
#include "swift/AST/Decl.h"
@@ -3089,15 +3090,110 @@
getAssocType(), getName(), None);
}
+static Type substGenericFunctionType(GenericFunctionType *genericFnType,
+ TypeSubstitutionFn substitutions,
+ LookupConformanceFn lookupConformances,
+ SubstOptions options) {
+ // Substitute into the function type (without generic signature).
+ auto *bareFnType = FunctionType::get(genericFnType->getInput(),
+ genericFnType->getResult(),
+ genericFnType->getExtInfo());
+ Type result =
+ Type(bareFnType).subst(substitutions, lookupConformances, options);
+ if (!result || result->is<ErrorType>()) return result;
+
+ auto *fnType = result->castTo<FunctionType>();
+ // Substitute generic parameters.
+ bool anySemanticChanges = false;
+ SmallVector<GenericTypeParamType *, 4> genericParams;
+ for (auto param : genericFnType->getGenericParams()) {
+ Type paramTy =
+ Type(param).subst(substitutions, lookupConformances, options);
+ if (!paramTy)
+ return Type();
+
+ if (auto newParam = paramTy->getAs<GenericTypeParamType>()) {
+ if (!newParam->isEqual(param))
+ anySemanticChanges = true;
+
+ genericParams.push_back(newParam);
+ } else {
+ anySemanticChanges = true;
+ }
+ }
+
+ // If no generic parameters remain, this is a non-generic function type.
+ if (genericParams.empty())
+ return result;
+
+ // Transform requirements.
+ SmallVector<Requirement, 4> requirements;
+ for (const auto &req : genericFnType->getRequirements()) {
+ // Substitute into the requirement.
+ auto substReqt = req.subst(substitutions, lookupConformances, options);
+ if (!substReqt) {
+ anySemanticChanges = true;
+ continue;
+ }
+
+ // Did anything change?
+ if (!anySemanticChanges &&
+ (!req.getFirstType()->isEqual(substReqt->getFirstType()) ||
+ (req.getKind() != RequirementKind::Layout &&
+ !req.getSecondType()->isEqual(substReqt->getSecondType())))) {
+ anySemanticChanges = true;
+ }
+
+ // Skip any erroneous requirements.
+ if (substReqt->getFirstType()->hasError() ||
+ (substReqt->getKind() != RequirementKind::Layout &&
+ substReqt->getSecondType()->hasError()))
+ continue;
+
+ requirements.push_back(*substReqt);
+ }
+
+ GenericSignature *genericSig = nullptr;
+ if (anySemanticChanges) {
+ // If there were semantic changes, we need to build a new generic
+ // signature.
+ GenericSignatureBuilder builder(genericFnType->getASTContext());
+
+ // Add the generic parameters to the builder.
+ for (auto gp : genericParams)
+ builder.addGenericParameter(gp);
+
+ // Add the requirements to the builder.
+ auto source =
+ GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
+ for (const auto &req : requirements)
+ builder.addRequirement(req, source, /*inferForModule=*/nullptr);
+
+ // Form the generic signature.
+ genericSig = std::move(builder).computeGenericSignature(SourceLoc());
+ } else {
+ // Use the mapped generic signature.
+ genericSig = GenericSignature::get(genericParams, requirements);
+ }
+
+ // Produce the new generic function type.
+ return GenericFunctionType::get(genericSig, fnType->getInput(),
+ fnType->getResult(), fnType->getExtInfo());
+}
+
static Type substType(Type derivedType,
TypeSubstitutionFn substitutions,
LookupConformanceFn lookupConformances,
SubstOptions options) {
+ // Handle substitutions into generic function types.
+ if (auto genericFnType = derivedType->getAs<GenericFunctionType>()) {
+ return substGenericFunctionType(genericFnType, substitutions,
+ lookupConformances, options);
+ }
// FIXME: Change getTypeOfMember() to not pass GenericFunctionType here
if (!derivedType->hasArchetype() &&
- !derivedType->hasTypeParameter() &&
- !derivedType->is<GenericFunctionType>())
+ !derivedType->hasTypeParameter())
return derivedType;
return derivedType.transformRec([&](TypeBase *type) -> Optional<Type> {
@@ -3409,6 +3505,7 @@
assert(memberType);
+ // Perform the substitution.
auto substitutions = getMemberSubstitutionMap(module, member);
return memberType.subst(substitutions, SubstFlags::UseErrorType);
}
@@ -3463,6 +3560,20 @@
return false;
}
+static bool transformSILYield(
+ SILYieldInfo &yield, bool &changed,
+ llvm::function_ref<Optional<Type>(TypeBase *)> fn) {
+ Type transType = yield.getType().transformRec(fn);
+ if (!transType) return true;
+
+ CanType canTransType = transType->getCanonicalType();
+ if (canTransType != yield.getType()) {
+ changed = true;
+ yield = yield.getWithType(canTransType);
+ }
+ return false;
+}
+
static bool transformSILParameter(
SILParameterInfo ¶m, bool &changed,
llvm::function_ref<Optional<Type>(TypeBase *)> fn) {
@@ -3568,6 +3679,12 @@
transInterfaceParams.push_back(param);
}
+ SmallVector<SILYieldInfo, 8> transInterfaceYields;
+ for (SILYieldInfo yield : fnTy->getYields()) {
+ if (transformSILYield(yield, changed, fn)) return Type();
+ transInterfaceYields.push_back(yield);
+ }
+
SmallVector<SILResultInfo, 8> transInterfaceResults;
for (SILResultInfo result : fnTy->getResults()) {
if (transformSILResult(result, changed, fn)) return Type();
@@ -3583,10 +3700,15 @@
if (!changed) return *this;
- return SILFunctionType::get(fnTy->getGenericSignature(), fnTy->getExtInfo(),
+ return SILFunctionType::get(fnTy->getGenericSignature(),
+ fnTy->getExtInfo(),
+ fnTy->getCoroutineKind(),
fnTy->getCalleeConvention(),
- transInterfaceParams, transInterfaceResults,
- transErrorResult, Ptr->getASTContext(),
+ transInterfaceParams,
+ transInterfaceYields,
+ transInterfaceResults,
+ transErrorResult,
+ Ptr->getASTContext(),
fnTy->getWitnessMethodConformanceOrNone());
}
@@ -3777,6 +3899,7 @@
return DependentMemberType::get(dependentBase, dependent->getName());
}
+ case TypeKind::GenericFunction:
case TypeKind::Function: {
auto function = cast<AnyFunctionType>(base);
auto inputTy = function->getInput().transformRec(fn);
@@ -3786,131 +3909,33 @@
if (!resultTy)
return Type();
- if (inputTy.getPointer() == function->getInput().getPointer() &&
- resultTy.getPointer() == function->getResult().getPointer())
- return *this;
+ bool isUnchanged =
+ inputTy.getPointer() == function->getInput().getPointer() &&
+ resultTy.getPointer() == function->getResult().getPointer();
+
+ if (auto genericFnType = dyn_cast<GenericFunctionType>(base)) {
+
+#ifndef NDEBUG
+ // Check that generic parameters won't be trasnformed.
+ // Transform generic parameters.
+ for (auto param : genericFnType->getGenericParams()) {
+ assert(Type(param).transformRec(fn).getPointer() == param &&
+ "GenericFunctionType transform() changes type parameter");
+ }
+#endif
+ if (isUnchanged) return *this;
+
+ auto genericSig = genericFnType->getGenericSignature();
+ return GenericFunctionType::get(genericSig, inputTy, resultTy,
+ function->getExtInfo());
+ }
+
+ if (isUnchanged) return *this;
return FunctionType::get(inputTy, resultTy,
function->getExtInfo());
}
- case TypeKind::GenericFunction: {
- GenericFunctionType *function = cast<GenericFunctionType>(base);
- bool anyChanges = false;
-
- // Transform generic parameters.
- SmallVector<GenericTypeParamType *, 4> genericParams;
- for (auto param : function->getGenericParams()) {
- Type paramTy = Type(param).transformRec(fn);
- if (!paramTy)
- return Type();
-
- if (auto newParam = paramTy->getAs<GenericTypeParamType>()) {
- if (newParam != param)
- anyChanges = true;
-
- genericParams.push_back(newParam);
- } else {
- anyChanges = true;
- }
- }
-
- // Transform requirements.
- SmallVector<Requirement, 4> requirements;
- for (const auto &req : function->getRequirements()) {
- auto firstType = req.getFirstType().transformRec(fn);
- if (!firstType)
- return Type();
-
- if (firstType.getPointer() != req.getFirstType().getPointer())
- anyChanges = true;
-
- if (req.getKind() == RequirementKind::Layout) {
- if (!firstType->isTypeParameter())
- continue;
-
- requirements.push_back(Requirement(req.getKind(), firstType,
- req.getLayoutConstraint()));
- continue;
- }
-
- Type secondType = req.getSecondType();
- if (secondType) {
- secondType = secondType.transformRec(fn);
- if (!secondType)
- return Type();
-
- if (secondType.getPointer() != req.getSecondType().getPointer())
- anyChanges = true;
- }
-
- if (!firstType->isTypeParameter()) {
- if (!secondType || !secondType->isTypeParameter())
- continue;
- std::swap(firstType, secondType);
- }
-
- requirements.push_back(Requirement(req.getKind(), firstType,
- secondType));
- }
-
- // Transform input type.
- auto inputTy = function->getInput().transformRec(fn);
- if (!inputTy)
- return Type();
-
- // Transform result type.
- auto resultTy = function->getResult().transformRec(fn);
- if (!resultTy)
- return Type();
-
- // Check whether anything changed.
- if (!anyChanges &&
- inputTy.getPointer() == function->getInput().getPointer() &&
- resultTy.getPointer() == function->getResult().getPointer())
- return *this;
-
- // If no generic parameters remain, this is a non-generic function type.
- if (genericParams.empty()) {
- return FunctionType::get(inputTy, resultTy, function->getExtInfo());
- }
-
- // Sort/unique the generic parameters by depth/index.
- using llvm::array_pod_sort;
- array_pod_sort(genericParams.begin(), genericParams.end(),
- [](GenericTypeParamType * const * gpp1,
- GenericTypeParamType * const * gpp2) {
- auto gp1 = *gpp1;
- auto gp2 = *gpp2;
-
- if (gp1->getDepth() < gp2->getDepth())
- return -1;
-
- if (gp1->getDepth() > gp2->getDepth())
- return 1;
-
- if (gp1->getIndex() < gp2->getIndex())
- return -1;
-
- if (gp1->getIndex() > gp2->getIndex())
- return 1;
-
- return 0;
- });
- genericParams.erase(std::unique(genericParams.begin(), genericParams.end(),
- [](GenericTypeParamType *gp1,
- GenericTypeParamType *gp2) {
- return gp1->getDepth() == gp2->getDepth()
- && gp1->getIndex() == gp2->getIndex();
- }),
- genericParams.end());
-
- // Produce the new generic function type.
- auto sig = GenericSignature::get(genericParams, requirements);
- return GenericFunctionType::get(sig, inputTy, resultTy,
- function->getExtInfo());
- }
-
case TypeKind::ArraySlice: {
auto slice = cast<ArraySliceType>(base);
auto baseTy = slice->getBaseType().transformRec(fn);
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 8d88e15..9700939 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -229,6 +229,10 @@
Opts.ParseStdlib |= Args.hasArg(OPT_parse_stdlib);
+ if (const Arg *A = Args.getLastArg(OPT_verify_generic_signatures)) {
+ Opts.VerifyGenericSignaturesInModule = A->getValue();
+ }
+
// Determine what the user has asked the frontend to do.
FrontendOptions::ActionType &Action = Opts.RequestedAction;
if (const Arg *A = Args.getLastArg(OPT_modes_Group)) {
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index fba8441..4682fc5 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -30,6 +30,7 @@
#include "swift/AST/ASTScope.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/AST/DiagnosticsSema.h"
+#include "swift/AST/GenericSignatureBuilder.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/LegacyASTTransformer.h"
@@ -630,6 +631,14 @@
ASTContext &Context = Instance.getASTContext();
+
+ auto verifyGenericSignaturesInModule =
+ Invocation.getFrontendOptions().VerifyGenericSignaturesInModule;
+ if (!verifyGenericSignaturesInModule.empty()) {
+ if (auto module = Context.getModuleByName(verifyGenericSignaturesInModule))
+ GenericSignatureBuilder::verifyGenericSignaturesInModule(module);
+ }
+
if (Invocation.getMigratorOptions().shouldRunMigrator()) {
migrator::updateCodeAndEmitRemap(&Instance, Invocation);
}
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 5e5e9b2..74e2f0e 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -3138,11 +3138,10 @@
metaclass = llvm::ConstantExpr::getBitCast(metaclass, TypeMetadataPtrTy);
// Get a reference count of two.
- auto *strongRefCountInit = llvm::ConstantInt::get(
- Int32Ty,
- InlineRefCountBits(0 /*unowned ref count*/, 2 /*strong ref count*/)
+ auto *refCountInit = llvm::ConstantInt::get(
+ IntPtrTy,
+ InlineRefCountBits(1 /* "extra" strong ref count*/, 1 /* unowned count */)
.getBitsValue());
- auto *unownedRefCountInit = llvm::ConstantInt::get(Int32Ty, 0);
auto *count = llvm::ConstantInt::get(Int32Ty, utf8.size());
// Capacity is length plus one because of the implicitly added '\0'
@@ -3150,9 +3149,8 @@
auto *capacity = llvm::ConstantInt::get(Int32Ty, utf8.size() + 1);
auto *flags = llvm::ConstantInt::get(Int8Ty, 0);
- // FIXME: Big endian-ness.
llvm::Constant *heapObjectHeaderFields[] = {
- metaclass, strongRefCountInit, unownedRefCountInit
+ metaclass, refCountInit
};
auto *initRefCountStruct = llvm::ConstantStruct::get(
@@ -3216,11 +3214,10 @@
metaclass = llvm::ConstantExpr::getBitCast(metaclass, TypeMetadataPtrTy);
// Get a reference count of two.
- auto *strongRefCountInit = llvm::ConstantInt::get(
- Int32Ty,
- InlineRefCountBits(0 /*unowned ref count*/, 2 /*strong ref count*/)
+ auto *refCountInit = llvm::ConstantInt::get(
+ IntPtrTy,
+ InlineRefCountBits(1 /* "extra" strong ref count*/, 1 /* unowned count */)
.getBitsValue());
- auto *unownedRefCountInit = llvm::ConstantInt::get(Int32Ty, 0);
auto *count = llvm::ConstantInt::get(Int32Ty, utf16Length);
auto *capacity = llvm::ConstantInt::get(Int32Ty, utf16Length + 1);
@@ -3228,7 +3225,7 @@
auto *padding = llvm::ConstantInt::get(Int8Ty, 0);
llvm::Constant *heapObjectHeaderFields[] = {
- metaclass, strongRefCountInit, unownedRefCountInit
+ metaclass, refCountInit
};
auto *initRefCountStruct = llvm::ConstantStruct::get(
diff --git a/lib/IRGen/GenExistential.cpp b/lib/IRGen/GenExistential.cpp
index 9e7b6ed..4a0cabf 100644
--- a/lib/IRGen/GenExistential.cpp
+++ b/lib/IRGen/GenExistential.cpp
@@ -2128,7 +2128,7 @@
// Size = ((sizeof(HeapObject) + align) & ~align) + size
auto *heapHeaderSize = llvm::ConstantInt::get(
- IGF.IGM.SizeTy, getHeapHeaderSize(IGM).getValue());
+ IGF.IGM.SizeTy, IGM.RefCountedStructSize.getValue());
size = Builder.CreateAdd(
Builder.CreateAnd(Builder.CreateAdd(heapHeaderSize, alignmentMask),
Builder.CreateNot(alignmentMask)),
@@ -2222,7 +2222,7 @@
// StartOffset = ((sizeof(HeapObject) + align) & ~align)
auto *heapHeaderSize = llvm::ConstantInt::get(
- IGF.IGM.SizeTy, getHeapHeaderSize(IGM).getValue());
+ IGF.IGM.SizeTy, IGM.RefCountedStructSize.getValue());
auto *startOffset = Builder.CreateAnd(
Builder.CreateAdd(heapHeaderSize, alignmentMask),
Builder.CreateNot(alignmentMask));
diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp
index 198f9cc..b025fe7 100644
--- a/lib/IRGen/GenKeyPath.cpp
+++ b/lib/IRGen/GenKeyPath.cpp
@@ -700,11 +700,6 @@
fields.add(emitMetadataGenerator(rootTy));
fields.add(emitMetadataGenerator(valueTy));
- // TODO: 32-bit heap object header still has an extra word
- if (SizeTy == Int32Ty) {
- fields.addInt32(0);
- }
-
#ifndef NDEBUG
auto endOfObjectHeader = fields.getNextOffsetFromGlobal();
unsigned expectedObjectHeaderSize;
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 4797745..5b4c114 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -2594,8 +2594,10 @@
auto generics = ncGenerics->getCanonicalSignature();
CanSILFunctionType fnType = [&]() -> CanSILFunctionType {
return SILFunctionType::get(generics, SILFunctionType::ExtInfo(),
+ SILCoroutineKind::None,
/*callee*/ ParameterConvention::Direct_Unowned,
- /*params*/ {}, /*results*/ {}, /*error*/ None,
+ /*params*/ {}, /*yields*/ {},
+ /*results*/ {}, /*error*/ None,
IGM.Context);
}();
diff --git a/lib/IRGen/GenValueWitness.cpp b/lib/IRGen/GenValueWitness.cpp
index 348ceb8..fe7ac34 100644
--- a/lib/IRGen/GenValueWitness.cpp
+++ b/lib/IRGen/GenValueWitness.cpp
@@ -242,8 +242,8 @@
buffer.getAlignment());
auto *boxStart = IGF.Builder.CreateLoad(boxAddress);
auto *alignmentMask = type.getAlignmentMask(IGF, T);
- auto *heapHeaderSize =
- llvm::ConstantInt::get(IGM.SizeTy, getHeapHeaderSize(IGM).getValue());
+ auto *heapHeaderSize = llvm::ConstantInt::get(
+ IGM.SizeTy, IGM.RefCountedStructSize.getValue());
auto *startOffset =
Builder.CreateAnd(Builder.CreateAdd(heapHeaderSize, alignmentMask),
Builder.CreateNot(alignmentMask));
@@ -820,7 +820,7 @@
IGF.Builder.CreateStore(ptr, dest);
auto *alignmentMask = fixedTI.getStaticAlignmentMask(IGM);
auto *heapHeaderSize = llvm::ConstantInt::get(
- IGM.SizeTy, getHeapHeaderSize(IGM).getValue());
+ IGM.SizeTy, IGM.RefCountedStructSize.getValue());
auto *startOffset = IGF.Builder.CreateAnd(
IGF.Builder.CreateAdd(heapHeaderSize, alignmentMask),
IGF.Builder.CreateNot(alignmentMask));
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index b931047..27b1531 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -264,8 +264,11 @@
});
FullBoxMetadataPtrTy = FullBoxMetadataStructTy->getPointerTo(DefaultAS);
- llvm::Type *refCountedElts[] = {TypeMetadataPtrTy, Int32Ty, Int32Ty};
+ // This must match struct HeapObject in the runtime.
+ llvm::Type *refCountedElts[] = {TypeMetadataPtrTy, IntPtrTy};
RefCountedStructTy->setBody(refCountedElts);
+ RefCountedStructSize =
+ Size(DataLayout.getStructLayout(RefCountedStructTy)->getSizeInBytes());
PtrSize = Size(DataLayout.getPointerSize(DefaultAS));
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index b242a31..ca960d6 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -446,6 +446,7 @@
llvm::PointerType *WitnessTablePtrTy;
};
llvm::StructType *RefCountedStructTy;/// %swift.refcounted = type { ... }
+ Size RefCountedStructSize; /// sizeof(%swift.refcounted)
llvm::PointerType *RefCountedPtrTy; /// %swift.refcounted*
llvm::PointerType *WeakReferencePtrTy;/// %swift.weak_reference*
llvm::PointerType *UnownedReferencePtrTy;/// %swift.unowned_reference*
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index 6656db0..c5a5524 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -1024,6 +1024,8 @@
void visitCondBranchInst(CondBranchInst *i);
void visitReturnInst(ReturnInst *i);
void visitThrowInst(ThrowInst *i);
+ void visitUnwindInst(UnwindInst *i);
+ void visitYieldInst(YieldInst *i);
void visitSwitchValueInst(SwitchValueInst *i);
void visitSwitchEnumInst(SwitchEnumInst *i);
void visitSwitchEnumAddrInst(SwitchEnumAddrInst *i);
@@ -2470,6 +2472,20 @@
}
}
+void IRGenSILFunction::visitUnwindInst(swift::UnwindInst *i) {
+ IGM.unimplemented(i->getLoc().getSourceLoc(),
+ "unwind instruction");
+ Builder.CreateUnreachable();
+ Builder.emitBlock(createBasicBlock("unwind"));
+}
+
+void IRGenSILFunction::visitYieldInst(swift::YieldInst *i) {
+ IGM.unimplemented(i->getLoc().getSourceLoc(),
+ "yield instruction");
+ Builder.CreateUnreachable();
+ Builder.emitBlock(createBasicBlock("yield"));
+}
+
static llvm::BasicBlock *emitBBMapForSwitchValue(
IRGenSILFunction &IGF,
SmallVectorImpl<std::pair<SILValue, llvm::BasicBlock*>> &dests,
diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp
index 31069ff..80c2e9b 100644
--- a/lib/IRGen/LoadableByAddress.cpp
+++ b/lib/IRGen/LoadableByAddress.cpp
@@ -73,47 +73,60 @@
return true;
}
-static bool modResultType(GenericEnvironment *genEnv,
- CanSILFunctionType loweredTy,
- irgen::IRGenModule &Mod);
+static bool shouldTransformResults(GenericEnvironment *env,
+ CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM);
-static bool containsLargeLoadable(GenericEnvironment *GenericEnv,
- ArrayRef<SILParameterInfo> params,
- irgen::IRGenModule &Mod) {
- for (SILParameterInfo param : params) {
- SILType storageType = param.getSILStorageType();
- CanType currCanType = storageType.getSwiftRValueType();
- if (SILFunctionType *currSILFunctionType =
- dyn_cast<SILFunctionType>(currCanType.getPointer())) {
- if (containsLargeLoadable(GenericEnv,
- currSILFunctionType->getParameters(), Mod) ||
- modResultType(GenericEnv, CanSILFunctionType(currSILFunctionType),
- Mod)) {
- return true;
- }
- } else {
- switch (param.getConvention()) {
- case ParameterConvention::Indirect_In_Guaranteed:
- case ParameterConvention::Indirect_Inout:
- case ParameterConvention::Indirect_InoutAliasable:
- case ParameterConvention::Indirect_In: {
- continue;
- }
- default:
- break;
- }
- if (isLargeLoadableType(GenericEnv, storageType, Mod)) {
- return true;
- }
- }
+static bool shouldTransformFunctionType(GenericEnvironment *env,
+ CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM);
+
+static bool shouldTransformParameter(GenericEnvironment *env,
+ SILParameterInfo param,
+ irgen::IRGenModule &IGM) {
+ SILType storageType = param.getSILStorageType();
+
+ // FIXME: only function types and not recursively-transformable types?
+ if (auto fnType = storageType.getAs<SILFunctionType>())
+ return shouldTransformFunctionType(env, fnType, IGM);
+
+ switch (param.getConvention()) {
+ case ParameterConvention::Indirect_In_Guaranteed:
+ case ParameterConvention::Indirect_Inout:
+ case ParameterConvention::Indirect_InoutAliasable:
+ case ParameterConvention::Indirect_In:
+ return false;
+ default:
+ return isLargeLoadableType(env, storageType, IGM);
}
+}
+
+static bool shouldTransformFunctionType(GenericEnvironment *env,
+ CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM) {
+ if (shouldTransformResults(env, fnType, IGM))
+ return true;
+
+ for (auto param : fnType->getParameters()) {
+ if (shouldTransformParameter(env, param, IGM))
+ return true;
+ }
+
+ for (auto yield : fnType->getYields()) {
+ if (shouldTransformParameter(env, yield, IGM))
+ return true;
+ }
+
return false;
}
// Forward declarations - functions depend on each other
static SmallVector<SILParameterInfo, 4>
-getNewArgTys(GenericEnvironment *GenericEnv,
- SILFunctionType *currSILFunctionType, irgen::IRGenModule &Mod);
+getNewParameters(GenericEnvironment *env, CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM);
+static SmallVector<SILYieldInfo, 2>
+getNewYields(GenericEnvironment *env, CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM);
static SILType getNewSILType(GenericEnvironment *GenericEnv,
SILType storageType, irgen::IRGenModule &Mod);
@@ -135,11 +148,11 @@
static SmallVector<SILResultInfo, 2>
getNewResults(GenericEnvironment *GenericEnv,
- SILFunctionType *currSILFunctionType, irgen::IRGenModule &Mod) {
+ CanSILFunctionType fnType, irgen::IRGenModule &Mod) {
// Get new SIL Function results - same as old results UNLESS:
// 1) Function type results might have a different signature
// 2) Large loadables are replaced by @out version
- auto origResults = currSILFunctionType->getResults();
+ auto origResults = fnType->getResults();
SmallVector<SILResultInfo, 2> newResults;
for (auto result : origResults) {
SILType currResultTy = result.getSILStorageType();
@@ -152,8 +165,7 @@
result.getConvention());
newResults.push_back(newResult);
} else if ((newSILType != currResultTy) &&
- modResultType(GenericEnv,
- CanSILFunctionType(currSILFunctionType), Mod)) {
+ shouldTransformResults(GenericEnv, fnType, Mod)) {
// Case (2) Above
SILResultInfo newSILResultInfo(newSILType.getSwiftRValueType(),
ResultConvention::Indirect);
@@ -165,39 +177,28 @@
return newResults;
}
-static SILFunctionType *
-getNewSILFunctionTypePtr(GenericEnvironment *GenericEnv,
- SILFunctionType *currSILFunctionType,
- irgen::IRGenModule &Mod) {
- if (!modifiableFunction(CanSILFunctionType(currSILFunctionType))) {
- return currSILFunctionType;
+static CanSILFunctionType
+getNewSILFunctionType(GenericEnvironment *env,
+ CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM) {
+ if (!modifiableFunction(fnType)) {
+ return fnType;
}
- SmallVector<SILParameterInfo, 4> newArgTys =
- getNewArgTys(GenericEnv, currSILFunctionType, Mod);
- SILFunctionType *newSILFunctionType = SILFunctionType::get(
- currSILFunctionType->getGenericSignature(),
- currSILFunctionType->getExtInfo(),
- currSILFunctionType->getCalleeConvention(), newArgTys,
- getNewResults(GenericEnv, currSILFunctionType, Mod),
- currSILFunctionType->getOptionalErrorResult(),
- currSILFunctionType->getASTContext(),
- currSILFunctionType->getWitnessMethodConformanceOrNone());
- return newSILFunctionType;
-}
-
-static SILType getNewSILFunctionType(GenericEnvironment *GenericEnv,
- SILFunctionType *currSILFunctionType,
- irgen::IRGenModule &Mod) {
- if (!modifiableFunction(CanSILFunctionType(currSILFunctionType))) {
- SILType newSILType = SILType::getPrimitiveObjectType(
- currSILFunctionType->getCanonicalType());
- return newSILType;
- }
- SILFunctionType *newSILFunctionType =
- getNewSILFunctionTypePtr(GenericEnv, currSILFunctionType, Mod);
- SILType newSILType =
- SILType::getPrimitiveObjectType(newSILFunctionType->getCanonicalType());
- return newSILType;
+ auto newParams = getNewParameters(env, fnType, IGM);
+ auto newYields = getNewYields(env, fnType, IGM);
+ auto newResults = getNewResults(env, fnType, IGM);
+ auto newFnType = SILFunctionType::get(
+ fnType->getGenericSignature(),
+ fnType->getExtInfo(),
+ fnType->getCoroutineKind(),
+ fnType->getCalleeConvention(),
+ newParams,
+ newYields,
+ newResults,
+ fnType->getOptionalErrorResult(),
+ fnType->getASTContext(),
+ fnType->getWitnessMethodConformanceOrNone());
+ return newFnType;
}
// Get the function type or the optional function type
@@ -223,35 +224,22 @@
SILType storageType,
irgen::IRGenModule &Mod) {
SILType newSILType = storageType;
- CanType currCanType = storageType.getSwiftRValueType();
- OptionalTypeKind optKind;
- if (auto optionalType = currCanType.getAnyOptionalObjectType(optKind)) {
- assert(optKind != OptionalTypeKind::OTK_None &&
- "Expected Real Optional Type");
- if (auto *currSILFunctionType =
- dyn_cast<SILFunctionType>(optionalType.getPointer())) {
- if (containsLargeLoadable(GenericEnv,
- currSILFunctionType->getParameters(), Mod) ||
- modResultType(GenericEnv, CanSILFunctionType(currSILFunctionType),
- Mod)) {
+ if (auto objectType = storageType.getAnyOptionalObjectType()) {
+ if (auto fnType = objectType.getAs<SILFunctionType>()) {
+ if (shouldTransformFunctionType(GenericEnv, fnType, Mod)) {
+ auto newFnType = getNewSILFunctionType(GenericEnv, fnType, Mod);
newSILType =
- getNewSILFunctionType(GenericEnv, currSILFunctionType, Mod);
- currCanType = newSILType.getSwiftRValueType();
- auto newType = OptionalType::get(optKind, currCanType);
- CanType newCanType = newType->getCanonicalType();
- newSILType = SILType::getPrimitiveObjectType(newCanType);
- if (storageType.isAddress()) {
- newSILType = newSILType.getAddressType();
- }
+ SILType::getPrimitiveType(newFnType, storageType.getCategory());
+ newSILType = SILType::getOptionalType(newSILType);
}
}
}
return newSILType;
}
-static bool modResultType(GenericEnvironment *genEnv,
- CanSILFunctionType loweredTy,
- irgen::IRGenModule &Mod) {
+static bool shouldTransformResults(GenericEnvironment *genEnv,
+ CanSILFunctionType loweredTy,
+ irgen::IRGenModule &Mod) {
if (!modifiableFunction(loweredTy)) {
return false;
}
@@ -274,53 +262,55 @@
genEnv = getGenericEnvironment(F->getModule(), loweredTy);
}
- return modResultType(genEnv, loweredTy, Mod);
+ return shouldTransformResults(genEnv, loweredTy, Mod);
+}
+
+static SILParameterInfo
+getNewParameter(GenericEnvironment *env, SILParameterInfo param,
+ irgen::IRGenModule &IGM) {
+ SILType storageType = param.getSILStorageType();
+ SILType newOptFuncType =
+ getNewOptionalFunctionType(env, storageType, IGM);
+ if (newOptFuncType != storageType) {
+ return param.getWithType(newOptFuncType.getSwiftRValueType());
+ }
+
+ if (auto paramFnType = storageType.getAs<SILFunctionType>()) {
+ if (shouldTransformFunctionType(env, paramFnType, IGM)) {
+ auto newFnType = getNewSILFunctionType(env, paramFnType, IGM);
+ return param.getWithType(newFnType);
+ } else {
+ return param;
+ }
+ } else if (isLargeLoadableType(env, storageType, IGM)) {
+ return SILParameterInfo(storageType.getSwiftRValueType(),
+ ParameterConvention::Indirect_In_Constant);
+ } else {
+ return param;
+ }
}
static SmallVector<SILParameterInfo, 4>
-getNewArgTys(GenericEnvironment *GenericEnv,
- SILFunctionType *currSILFunctionType, irgen::IRGenModule &Mod) {
- ArrayRef<SILParameterInfo> params = currSILFunctionType->getParameters();
- SmallVector<SILParameterInfo, 4> newArgTys;
- for (SILParameterInfo param : params) {
- SILType storageType = param.getSILStorageType();
- SILType newOptFuncType =
- getNewOptionalFunctionType(GenericEnv, storageType, Mod);
- if (newOptFuncType != storageType) {
- auto newParam = SILParameterInfo(newOptFuncType.getSwiftRValueType(),
- param.getConvention());
- newArgTys.push_back(newParam);
- continue;
- }
- CanType currCanType = storageType.getSwiftRValueType();
- if (SILFunctionType *currSILFunctionType =
- dyn_cast<SILFunctionType>(currCanType.getPointer())) {
- if (containsLargeLoadable(GenericEnv,
- currSILFunctionType->getParameters(), Mod) ||
- modResultType(GenericEnv, CanSILFunctionType(currSILFunctionType),
- Mod)) {
- SILType newSILType =
- getNewSILFunctionType(GenericEnv, currSILFunctionType, Mod);
- if (storageType.isAddress()) {
- newSILType = newSILType.getAddressType();
- }
- auto newParam = SILParameterInfo(newSILType.getSwiftRValueType(),
- param.getConvention());
- newArgTys.push_back(newParam);
- } else {
- newArgTys.push_back(param);
- }
- } else if (isLargeLoadableType(GenericEnv, storageType, Mod)) {
- SILType addrType = storageType.getAddressType();
- auto newParam =
- SILParameterInfo(addrType.getSwiftRValueType(),
- ParameterConvention::Indirect_In_Constant);
- newArgTys.push_back(newParam);
- } else {
- newArgTys.push_back(param);
- }
+getNewParameters(GenericEnvironment *env, CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM) {
+ SmallVector<SILParameterInfo, 4> newParams;
+ for (SILParameterInfo param : fnType->getParameters()) {
+ auto newParam = getNewParameter(env, param, IGM);
+ newParams.push_back(newParam);
}
- return newArgTys;
+ return newParams;
+}
+
+static SmallVector<SILYieldInfo, 2>
+getNewYields(GenericEnvironment *env, CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM) {
+ SmallVector<SILYieldInfo, 2> newYields;
+ for (auto oldYield : fnType->getYields()) {
+ auto newYieldAsParam = getNewParameter(env, oldYield, IGM);
+ newYields.push_back(SILYieldInfo(newYieldAsParam.getType(),
+ newYieldAsParam.getConvention()));
+ }
+ return newYields;
}
static SILType getNewSILType(GenericEnvironment *GenericEnv,
@@ -329,17 +319,11 @@
if (newSILType != storageType) {
return newSILType;
}
- CanType currCanType = storageType.getSwiftRValueType();
- if (SILFunctionType *currSILFunctionType =
- dyn_cast<SILFunctionType>(currCanType.getPointer())) {
- if (containsLargeLoadable(GenericEnv, currSILFunctionType->getParameters(),
- Mod) ||
- modResultType(GenericEnv, CanSILFunctionType(currSILFunctionType),
- Mod)) {
- newSILType = getNewSILFunctionType(GenericEnv, currSILFunctionType, Mod);
- if (storageType.isAddress()) {
- newSILType = newSILType.getAddressType();
- }
+ if (auto fnType = storageType.getAs<SILFunctionType>()) {
+ if (shouldTransformFunctionType(GenericEnv, fnType, Mod)) {
+ auto newFnType = getNewSILFunctionType(GenericEnv, fnType, Mod);
+ newSILType = SILType::getPrimitiveType(newFnType,
+ storageType.getCategory());
}
} else if (isLargeLoadableType(GenericEnv, storageType, Mod)) {
newSILType = storageType.getAddressType();
@@ -584,14 +568,14 @@
return;
}
// Check callee - need new generic env:
- SILFunctionType *origSILFunctionType = applySite.getSubstCalleeType();
+ CanSILFunctionType origSILFunctionType = applySite.getSubstCalleeType();
GenericEnvironment *genEnvCallee = nullptr;
if (origSILFunctionType->isPolymorphic()) {
genEnvCallee = getGenericEnvironment(
applySite.getModule(), CanSILFunctionType(origSILFunctionType));
}
- SILFunctionType *newSILFunctionType =
- getNewSILFunctionTypePtr(genEnvCallee, origSILFunctionType, pass.Mod);
+ auto newSILFunctionType =
+ getNewSILFunctionType(genEnvCallee, origSILFunctionType, pass.Mod);
if (origSILFunctionType != newSILFunctionType) {
pass.applies.push_back(applySite.getInstruction());
}
@@ -617,27 +601,19 @@
return;
}
SILType currSILType = instr->getType();
- CanType currCanType = currSILType.getSwiftRValueType();
- SILFunctionType *currSILFunctionType =
- dyn_cast<SILFunctionType>(currCanType.getPointer());
- if (!currSILFunctionType) {
- llvm_unreachable("unsupported type");
- }
+ auto fnType = currSILType.castTo<SILFunctionType>();
+
GenericEnvironment *genEnv = nullptr;
- if (currSILFunctionType->isPolymorphic()) {
- genEnv = getGenericEnvironment(instr->getModule(),
- CanSILFunctionType(currSILFunctionType));
+ if (fnType->isPolymorphic()) {
+ genEnv = getGenericEnvironment(instr->getModule(), fnType);
}
Lowering::GenericContextScope GenericScope(
- instr->getModule().Types, currSILFunctionType->getGenericSignature());
- if (containsLargeLoadable(genEnv, currSILFunctionType->getParameters(),
- pass.Mod) ||
- modResultType(genEnv, CanSILFunctionType(currSILFunctionType),
- pass.Mod)) {
+ instr->getModule().Types, fnType->getGenericSignature());
+ if (shouldTransformFunctionType(genEnv, fnType, pass.Mod)) {
pass.methodInstsToMod.push_back(instr);
return;
}
- if (newResultsDiffer(genEnv, currSILFunctionType->getResults(), pass.Mod)) {
+ if (newResultsDiffer(genEnv, fnType->getResults(), pass.Mod)) {
pass.methodInstsToMod.push_back(instr);
}
}
@@ -763,8 +739,8 @@
if (!genEnv && canFuncType->isPolymorphic()) {
genEnv = getGenericEnvironment(instr->getModule(), canFuncType);
}
- SILFunctionType *newSILFunctionType =
- getNewSILFunctionTypePtr(genEnv, funcType, pass.Mod);
+ auto newSILFunctionType =
+ getNewSILFunctionType(genEnv, funcType, pass.Mod);
if (funcType != newSILFunctionType) {
pass.tupleInstsToMod.push_back(instr);
}
@@ -1255,23 +1231,22 @@
if (!modifiableApply(applySite, pass.Mod)) {
continue;
}
- SILFunctionType *origSILFunctionType = applySite.getSubstCalleeType();
- auto canSILFunctionType = CanSILFunctionType(origSILFunctionType);
+ CanSILFunctionType origSILFunctionType = applySite.getSubstCalleeType();
Lowering::GenericContextScope GenericScope(
- silModue.Types, canSILFunctionType->getGenericSignature());
+ silModue.Types, origSILFunctionType->getGenericSignature());
GenericEnvironment *genEnv = nullptr;
if (origSILFunctionType->isPolymorphic()) {
- genEnv = getGenericEnvironment(silModue, canSILFunctionType);
+ genEnv = getGenericEnvironment(silModue, origSILFunctionType);
}
- if (!modResultType(genEnv, canSILFunctionType, pass.Mod)) {
+ if (!shouldTransformResults(genEnv, origSILFunctionType, pass.Mod)) {
continue;
}
- auto singleResult = canSILFunctionType->getSingleResult();
+ auto singleResult = origSILFunctionType->getSingleResult();
auto resultStorageType = singleResult.getSILStorageType();
if (!isLargeLoadableType(genEnv, resultStorageType, pass.Mod)) {
// Make sure it is a function type
auto canType = resultStorageType.getSwiftRValueType();
- if (!dyn_cast<SILFunctionType>(canType.getPointer())) {
+ if (!isa<SILFunctionType>(canType)) {
// Check if it is an optional funciton type
OptionalTypeKind optKind;
auto optionalType = canType.getAnyOptionalObjectType(optKind);
@@ -1607,19 +1582,16 @@
}
static void castTupleInstr(SingleValueInstruction *instr, IRGenModule &Mod) {
- SILType currSILType = instr->getType().getObjectType();
- CanType currCanType = currSILType.getSwiftRValueType();
- SILFunctionType *funcType = dyn_cast<SILFunctionType>(currCanType);
- assert(funcType && "Expected SILFunctionType as tuple's return");
- CanSILFunctionType canFuncType = CanSILFunctionType(funcType);
+ SILType currSILType = instr->getType();
+ auto funcType = currSILType.castTo<SILFunctionType>();
GenericEnvironment *genEnv = instr->getFunction()->getGenericEnvironment();
- if (!genEnv && canFuncType->isPolymorphic()) {
- genEnv = getGenericEnvironment(instr->getModule(), canFuncType);
+ if (!genEnv && funcType->isPolymorphic()) {
+ genEnv = getGenericEnvironment(instr->getModule(), funcType);
}
- SILType newSILType = getNewSILFunctionType(genEnv, funcType, Mod);
- if (currSILType.isAddress()) {
- newSILType = newSILType.getAddressType();
- }
+ auto newFnType = getNewSILFunctionType(genEnv, funcType, Mod);
+ SILType newSILType =
+ SILType::getPrimitiveType(newFnType, currSILType.getCategory());
+
auto II = instr->getIterator();
++II;
SILBuilder castBuilder(II);
@@ -1993,16 +1965,14 @@
for (MethodInst *instr : pass.methodInstsToMod) {
SILType currSILType = instr->getType();
- CanType currCanType = currSILType.getSwiftRValueType();
- SILFunctionType *currSILFunctionType =
- dyn_cast<SILFunctionType>(currCanType.getPointer());
+ auto currSILFunctionType = currSILType.castTo<SILFunctionType>();
GenericEnvironment *genEnvForMethod = nullptr;
if (currSILFunctionType->isPolymorphic()) {
genEnvForMethod = getGenericEnvironment(
instr->getModule(), CanSILFunctionType(currSILFunctionType));
}
- SILType newSILType =
- getNewSILFunctionType(genEnvForMethod, currSILFunctionType, pass.Mod);
+ SILType newSILType = SILType::getPrimitiveObjectType(
+ getNewSILFunctionType(genEnvForMethod, currSILFunctionType, pass.Mod));
auto member = instr->getMember();
auto loc = instr->getLoc();
SILBuilder methodBuilder(instr);
@@ -2104,7 +2074,9 @@
origResultInfo.getConvention());
auto NewTy = SILFunctionType::get(
loweredTy->getGenericSignature(), loweredTy->getExtInfo(),
+ loweredTy->getCoroutineKind(),
loweredTy->getCalleeConvention(), loweredTy->getParameters(),
+ loweredTy->getYields(),
newSILResultInfo, loweredTy->getOptionalErrorResult(),
F->getModule().getASTContext(),
loweredTy->getWitnessMethodConformanceOrNone());
@@ -2131,10 +2103,8 @@
if (!genEnv && loweredTy->isPolymorphic()) {
genEnv = getGenericEnvironment(F->getModule(), loweredTy);
}
- if (containsLargeLoadable(
- genEnv, F->getLoweredFunctionType()->getParameters(), *currIRMod) ||
- modResultType(genEnv, CanSILFunctionType(F->getLoweredFunctionType()),
- *currIRMod)) {
+ if (shouldTransformFunctionType(genEnv, F->getLoweredFunctionType(),
+ *currIRMod)) {
modFuncs.insert(F);
}
return;
@@ -2178,16 +2148,15 @@
getOperandTypeWithCastIfNecessary(SILInstruction *containingInstr, SILValue op,
IRGenModule &Mod, SILBuilder &builder) {
SILType currSILType = op->getType();
- CanType currCanType = currSILType.getSwiftRValueType();
- SILFunctionType *funcType = dyn_cast<SILFunctionType>(currCanType);
- if (funcType) {
+ if (auto funcType = currSILType.getAs<SILFunctionType>()) {
CanSILFunctionType canFuncType = CanSILFunctionType(funcType);
GenericEnvironment *genEnv =
containingInstr->getFunction()->getGenericEnvironment();
if (!genEnv && canFuncType->isPolymorphic()) {
genEnv = getGenericEnvironment(containingInstr->getModule(), canFuncType);
}
- SILType newSILType = getNewSILFunctionType(genEnv, funcType, Mod);
+ auto newFnType = getNewSILFunctionType(genEnv, funcType, Mod);
+ SILType newSILType = SILType::getPrimitiveObjectType(newFnType);
if (currSILType.isAddress()) {
newSILType = newSILType.getAddressType(); // we need address for loads
if (newSILType != currSILType) {
@@ -2242,7 +2211,7 @@
callee = applySite.getCallee();
}
}
- SILFunctionType *origSILFunctionType = applySite.getSubstCalleeType();
+ CanSILFunctionType origSILFunctionType = applySite.getSubstCalleeType();
auto origCanType = CanSILFunctionType(origSILFunctionType);
Lowering::GenericContextScope GenericScope(
getModule()->Types, origCanType->getGenericSignature());
@@ -2251,8 +2220,8 @@
genEnv = getGenericEnvironment(applyInst->getModule(),
CanSILFunctionType(origSILFunctionType));
}
- SILFunctionType *newSILFunctionType =
- getNewSILFunctionTypePtr(genEnv, origSILFunctionType, *currIRMod);
+ CanSILFunctionType newSILFunctionType =
+ getNewSILFunctionType(genEnv, origSILFunctionType, *currIRMod);
CanSILFunctionType newCanSILFuncType(newSILFunctionType);
SILFunctionConventions newSILFunctionConventions(newCanSILFuncType,
*getModule());
@@ -2432,23 +2401,19 @@
if (auto *thinToPointer = dyn_cast<ThinFunctionToPointerInst>(convInstr)) {
currSILType = thinToPointer->getOperand()->getType();
}
- CanType currCanType = currSILType.getSwiftRValueType();
- SILFunctionType *currSILFunctionType =
- dyn_cast<SILFunctionType>(currCanType.getPointer());
+ auto currSILFunctionType = currSILType.castTo<SILFunctionType>();
Lowering::GenericContextScope GenericScope(
getModule()->Types,
- CanSILFunctionType(currSILFunctionType)->getGenericSignature());
- if (!currSILFunctionType) {
- llvm_unreachable("unsupported type");
- }
+ currSILFunctionType->getGenericSignature());
GenericEnvironment *genEnv =
convInstr->getFunction()->getGenericEnvironment();
auto loweredTy = convInstr->getFunction()->getLoweredFunctionType();
if (!genEnv && loweredTy->isPolymorphic()) {
genEnv = getGenericEnvironment(convInstr->getModule(), loweredTy);
}
- SILType newType =
+ CanSILFunctionType newFnType =
getNewSILFunctionType(genEnv, currSILFunctionType, *currIRMod);
+ SILType newType = SILType::getPrimitiveObjectType(newFnType);
SILBuilder convBuilder(convInstr);
SingleValueInstruction *newInstr = nullptr;
switch (convInstr->getKind()) {
@@ -2511,7 +2476,6 @@
void LoadableByAddress::updateLoweredTypes(SILFunction *F) {
IRGenModule *currIRMod = getIRGenModule()->IRGen.getGenModule(F);
CanSILFunctionType funcType = F->getLoweredFunctionType();
- auto *currSILFunctionType = dyn_cast<SILFunctionType>(funcType.getPointer());
Lowering::GenericContextScope GenericScope(getModule()->Types,
funcType->getGenericSignature());
GenericEnvironment *genEnv = F->getGenericEnvironment();
@@ -2519,10 +2483,8 @@
if (!genEnv && loweredTy->isPolymorphic()) {
genEnv = getGenericEnvironment(F->getModule(), loweredTy);
}
- auto *newFuncTy =
- getNewSILFunctionTypePtr(genEnv, currSILFunctionType, *currIRMod);
-
- F->rewriteLoweredTypeUnsafe(CanSILFunctionType(newFuncTy));
+ auto newFuncTy = getNewSILFunctionType(genEnv, funcType, *currIRMod);
+ F->rewriteLoweredTypeUnsafe(newFuncTy);
}
/// The entry point to this function transformation.
diff --git a/lib/IRGen/StructLayout.cpp b/lib/IRGen/StructLayout.cpp
index e27403f..003caf3 100644
--- a/lib/IRGen/StructLayout.cpp
+++ b/lib/IRGen/StructLayout.cpp
@@ -38,11 +38,6 @@
llvm_unreachable("bad layout kind!");
}
-/// Return the size of the standard heap header.
-Size irgen::getHeapHeaderSize(IRGenModule &IGM) {
- return IGM.getPointerSize() + Size(8);
-}
-
/// Perform structure layout on the given types.
StructLayout::StructLayout(IRGenModule &IGM, CanType astTy,
LayoutKind layoutKind,
@@ -184,7 +179,7 @@
void StructLayoutBuilder::addHeapHeader() {
assert(StructFields.empty() && "adding heap header at a non-zero offset");
- CurSize = getHeapHeaderSize(IGM);
+ CurSize = IGM.RefCountedStructSize;
CurAlignment = IGM.getPointerAlignment();
StructFields.push_back(IGM.RefCountedStructTy);
}
diff --git a/lib/IRGen/StructLayout.h b/lib/IRGen/StructLayout.h
index 70c1531..84128b8 100644
--- a/lib/IRGen/StructLayout.h
+++ b/lib/IRGen/StructLayout.h
@@ -395,8 +395,6 @@
const llvm::Twine &name = "") const;
};
-Size getHeapHeaderSize(IRGenModule &IGM);
-
/// Different policies for accessing a physical field.
enum class FieldAccess : uint8_t {
/// Instance variable offsets are constant.
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index d3a64cc..37bcfe2 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -473,7 +473,6 @@
Tok.setKind(tok::oper_prefix);
LLVM_FALLTHROUGH;
case tok::oper_prefix:
- SyntaxContext->addTokenSyntax(Tok.getLoc());
Operator = parseExprOperator();
break;
case tok::oper_binary_spaced:
@@ -867,7 +866,8 @@
lSquareLoc, indexArgs, indexArgLabels,
indexArgLabelLocs,
rSquareLoc,
- trailingClosure);
+ trailingClosure,
+ SyntaxKind::Unknown);
if (status.hasCodeCompletion())
return makeParserCodeCompletionResult<Expr>();
if (status.isError())
@@ -1216,7 +1216,8 @@
ParserStatus status = parseExprList(
tok::l_square, tok::r_square,
/*isPostfix=*/true, isExprBasic, lSquareLoc, indexArgs,
- indexArgLabels, indexArgLabelLocs, rSquareLoc, trailingClosure);
+ indexArgLabels, indexArgLabelLocs, rSquareLoc, trailingClosure,
+ SyntaxKind::Unknown);
if (status.hasCodeCompletion())
return makeParserCodeCompletionResult<Expr>();
if (status.isError() || Result.isNull())
@@ -1389,8 +1390,7 @@
case tok::integer_literal: {
StringRef Text = copyAndStripUnderscores(Context, Tok.getText());
SourceLoc Loc = consumeToken(tok::integer_literal);
- SyntaxContext->addTokenSyntax(Loc);
- SyntaxContext->makeNode(SyntaxKind::IntegerLiteralExpr);
+ SyntaxContext->makeNode(SyntaxKind::IntegerLiteralExpr, Loc);
Result = makeParserResult(new (Context) IntegerLiteralExpr(Text, Loc,
/*Implicit=*/false));
break;
@@ -1398,8 +1398,7 @@
case tok::floating_literal: {
StringRef Text = copyAndStripUnderscores(Context, Tok.getText());
SourceLoc Loc = consumeToken(tok::floating_literal);
- SyntaxContext->addTokenSyntax(Loc);
- SyntaxContext->makeNode(SyntaxKind::FloatLiteralExpr);
+ SyntaxContext->makeNode(SyntaxKind::FloatLiteralExpr, Loc);
Result = makeParserResult(new (Context) FloatLiteralExpr(Text, Loc,
/*Implicit=*/false));
break;
@@ -1608,7 +1607,8 @@
lParenLoc, args, argLabels,
argLabelLocs,
rParenLoc,
- trailingClosure);
+ trailingClosure,
+ SyntaxKind::FunctionCallArgumentList);
if (status.isError())
return nullptr;
@@ -1657,7 +1657,8 @@
}
case tok::l_paren:
- Result = parseExprList(tok::l_paren, tok::r_paren);
+ Result = parseExprList(tok::l_paren, tok::r_paren,
+ SyntaxKind::FunctionCallArgumentList);
break;
case tok::l_square:
@@ -1805,8 +1806,7 @@
Token EntireTok = Tok;
// Create a syntax node for string literal.
- SyntaxContext->addTokenSyntax(Tok.getLoc());
- SyntaxContext->makeNode(SyntaxKind::StringLiteralExpr);
+ SyntaxContext->makeNode(SyntaxKind::StringLiteralExpr, Tok.getLoc());
SyntaxParsingContextChild LocalContext(SyntaxContext,
SyntaxContextKind::Expr);
@@ -1883,7 +1883,8 @@
assert(Tok.is(tok::l_paren));
TokReceiver->registerTokenKindChange(Tok.getLoc(),
tok::string_interpolation_anchor);
- ParserResult<Expr> E = parseExprList(tok::l_paren, tok::r_paren);
+ ParserResult<Expr> E = parseExprList(tok::l_paren, tok::r_paren,
+ SyntaxKind::Unknown);
Status |= E;
if (E.isNonNull()) {
Exprs.push_back(E.get());
@@ -1995,6 +1996,11 @@
SourceLoc lparenLoc = consumeToken(tok::l_paren);
SourceLoc rparenLoc;
while (true) {
+ SyntaxParsingContextChild DisabledContext(SyntaxContext,
+ SyntaxContextKind::Expr);
+ // The following code may backtrack; so we disable the syntax tree creation
+ // in this scope.
+ DisabledContext.disable();
// Terminate at ')'.
if (Tok.is(tok::r_paren)) {
rparenLoc = consumeToken(tok::r_paren);
@@ -2752,7 +2758,8 @@
/// expr-paren-element:
/// (identifier ':')? expr
///
-ParserResult<Expr> Parser::parseExprList(tok leftTok, tok rightTok) {
+ParserResult<Expr>
+Parser::parseExprList(tok leftTok, tok rightTok, SyntaxKind Kind) {
SmallVector<Expr*, 8> subExprs;
SmallVector<Identifier, 8> subExprNames;
SmallVector<SourceLoc, 8> subExprNameLocs;
@@ -2766,7 +2773,8 @@
subExprNames,
subExprNameLocs,
rightLoc,
- trailingClosure);
+ trailingClosure,
+ Kind);
// A tuple with a single, unlabeled element is just parentheses.
if (subExprs.size() == 1 &&
@@ -2801,7 +2809,8 @@
SmallVectorImpl<Identifier> &exprLabels,
SmallVectorImpl<SourceLoc> &exprLabelLocs,
SourceLoc &rightLoc,
- Expr *&trailingClosure) {
+ Expr *&trailingClosure,
+ SyntaxKind Kind) {
trailingClosure = nullptr;
StructureMarkerRAII ParsingExprList(*this, Tok);
@@ -2812,6 +2821,7 @@
rightTok == tok::r_paren
? diag::expected_rparen_expr_list
: diag::expected_rsquare_expr_list,
+ Kind,
[&] () -> ParserStatus {
Identifier FieldName;
SourceLoc FieldNameLoc;
@@ -2823,6 +2833,8 @@
ParserStatus Status;
Expr *SubExpr = nullptr;
if (Tok.isBinaryOperator() && peekToken().isAny(rightTok, tok::comma)) {
+ SyntaxParsingContextChild operatorContext(SyntaxContext,
+ SyntaxContextKind::Expr);
SourceLoc Loc;
Identifier OperName;
if (parseAnyIdentifier(OperName, Loc, diag::expected_operator_ref)) {
@@ -2963,7 +2975,8 @@
lParenLoc, args, argLabels,
argLabelLocs,
rParenLoc,
- trailingClosure);
+ trailingClosure,
+ SyntaxKind::FunctionCallArgumentList);
if (status.hasCodeCompletion())
return makeParserCodeCompletionResult<Expr>();
if (status.isError())
@@ -3055,7 +3068,8 @@
lParenLoc, args, argLabels,
argLabelLocs,
rParenLoc,
- trailingClosure);
+ trailingClosure,
+ SyntaxKind::FunctionCallArgumentList);
// Form the call.
auto Result = makeParserResult(status | fn,
@@ -3151,6 +3165,7 @@
Status |= parseList(tok::r_square, LSquareLoc, RSquareLoc,
/*AllowSepAfterLast=*/true,
diag::expected_rsquare_array_expr,
+ SyntaxKind::Unknown,
[&] () -> ParserStatus
{
ParserResult<Expr> Element
@@ -3199,7 +3214,9 @@
Status |=
parseList(tok::r_square, LSquareLoc, RSquareLoc,
/*AllowSepAfterLast=*/true,
- diag::expected_rsquare_array_expr, [&]() -> ParserStatus {
+ diag::expected_rsquare_array_expr,
+ SyntaxKind::Unknown,
+ [&]() -> ParserStatus {
// Parse the next key.
ParserResult<Expr> Key;
if (FirstPair) {
diff --git a/lib/Parse/ParsePattern.cpp b/lib/Parse/ParsePattern.cpp
index 09c2496..352e927 100644
--- a/lib/Parse/ParsePattern.cpp
+++ b/lib/Parse/ParsePattern.cpp
@@ -19,10 +19,15 @@
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Initializer.h"
#include "swift/Basic/StringExtras.h"
+#include "swift/Syntax/SyntaxFactory.h"
+#include "swift/Syntax/TokenSyntax.h"
+#include "swift/Syntax/SyntaxParsingContext.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/SaveAndRestore.h"
+
using namespace swift;
+using namespace swift::syntax;
/// \brief Determine the kind of a default argument given a parsed
/// expression that has not yet been type-checked.
@@ -162,6 +167,7 @@
return parseList(tok::r_paren, leftParenLoc, rightParenLoc,
/*AllowSepAfterLast=*/false,
diag::expected_rparen_parameter,
+ SyntaxKind::Unknown,
[&]() -> ParserStatus {
ParsedParameter param;
ParserStatus status;
@@ -795,7 +801,8 @@
/*isExprBasic=*/false,
lParenLoc, args, argLabels,
argLabelLocs, rParenLoc,
- trailingClosure);
+ trailingClosure,
+ SyntaxKind::Unknown);
if (status.isSuccess()) {
backtrack.cancelBacktrack();
@@ -947,6 +954,7 @@
parseList(tok::r_paren, LPLoc, RPLoc,
/*AllowSepAfterLast=*/false,
diag::expected_rparen_tuple_pattern_list,
+ SyntaxKind::Unknown,
[&] () -> ParserStatus {
// Parse the pattern tuple element.
ParserStatus EltStatus;
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index aa7059c..5a91fae 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -592,17 +592,14 @@
}
SyntaxParsingContextChild LocalContext(SyntaxContext, SyntaxKind::CodeBlock);
SourceLoc LBLoc = consumeToken(tok::l_brace);
- LocalContext.addTokenSyntax(LBLoc);
SmallVector<ASTNode, 16> Entries;
SourceLoc RBLoc;
ParserStatus Status = parseBraceItems(Entries, BraceItemListKind::Brace,
BraceItemListKind::Brace);
- if (!parseMatchingToken(tok::r_brace, RBLoc,
- diag::expected_rbrace_in_brace_stmt, LBLoc)) {
- LocalContext.addTokenSyntax(RBLoc);
- }
+ parseMatchingToken(tok::r_brace, RBLoc,
+ diag::expected_rbrace_in_brace_stmt, LBLoc);
return makeParserResult(Status,
BraceStmt::create(Context, LBLoc, Entries, RBLoc));
diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp
index bf66864..9ff7c0f 100644
--- a/lib/Parse/ParseType.cpp
+++ b/lib/Parse/ParseType.cpp
@@ -19,6 +19,9 @@
#include "swift/AST/TypeLoc.h"
#include "swift/Parse/Lexer.h"
#include "swift/Parse/CodeCompletionCallbacks.h"
+#include "swift/Syntax/SyntaxFactory.h"
+#include "swift/Syntax/TokenSyntax.h"
+#include "swift/Syntax/SyntaxParsingContext.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
@@ -26,6 +29,7 @@
#include "llvm/Support/SaveAndRestore.h"
using namespace swift;
+using namespace swift::syntax;
TypeRepr *Parser::applyAttributeToType(TypeRepr *ty,
const TypeAttributes &attrs,
@@ -794,6 +798,7 @@
ParserStatus Status = parseList(tok::r_paren, LPLoc, RPLoc,
/*AllowSepAfterLast=*/false,
diag::expected_rparen_tuple_type_list,
+ SyntaxKind::Unknown,
[&] () -> ParserStatus {
TupleTypeReprElement element;
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index a5d5c6d..aa9444d 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -35,6 +35,7 @@
#include "llvm/ADT/Twine.h"
using namespace swift;
+using namespace swift::syntax;
void DelayedParsingCallbacks::anchor() { }
void SILParserTUStateBase::anchor() { }
@@ -127,6 +128,14 @@
}
} // unnamed namespace
+
+swift::Parser::BacktrackingScope::~BacktrackingScope() {
+ if (Backtrack) {
+ P.backtrackToPosition(PP);
+ DT.abort();
+ }
+}
+
void swift::performDelayedParsing(
DeclContext *DC, PersistentParserState &PersistentState,
CodeCompletionCallbacksFactory *CodeCompletionFactory) {
@@ -438,8 +447,8 @@
TokReceiver(SF.shouldKeepSyntaxInfo() ?
new TokenRecorder(SF) :
new ConsumeTokenReceiver()),
- SyntaxContext(new syntax::SyntaxParsingContextRoot(SF, L->getBufferID(), Tok)) {
-
+ SyntaxContext(new syntax::SyntaxParsingContextRoot(SF, L->getBufferID(),
+ Tok)) {
State = PersistentState;
if (!State) {
OwnedState.reset(new PersistentParserState());
@@ -819,10 +828,15 @@
ParserStatus
Parser::parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
- bool AllowSepAfterLast, Diag<> ErrorDiag,
+ bool AllowSepAfterLast, Diag<> ErrorDiag, SyntaxKind Kind,
std::function<ParserStatus()> callback) {
+ std::unique_ptr<SyntaxParsingContext> pListContext;
+ if (Kind == SyntaxKind::FunctionCallArgumentList) {
+ pListContext.reset(new SyntaxParsingContextChild(SyntaxContext, Kind));
+ }
if (Tok.is(RightK)) {
+ pListContext.reset();
RightLoc = consumeToken(RightK);
return makeParserSuccess();
}
@@ -835,6 +849,11 @@
consumeToken();
}
SourceLoc StartLoc = Tok.getLoc();
+ std::unique_ptr<SyntaxParsingContext> pElementContext;
+ if (Kind == SyntaxKind::FunctionCallArgumentList) {
+ pElementContext.reset(new SyntaxParsingContextChild(SyntaxContext,
+ SyntaxKind::FunctionCallArgument));
+ }
Status |= callback();
if (Tok.is(RightK))
break;
@@ -878,6 +897,7 @@
Status.setIsParseError();
}
+ pListContext.reset();
if (Status.isError()) {
// If we've already got errors, don't emit missing RightK diagnostics.
RightLoc = Tok.is(RightK) ? consumeToken() : PreviousLoc;
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index cc7166e..8fd9a96 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -28,10 +28,13 @@
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILUndef.h"
#include "swift/SIL/TypeLowering.h"
+#include "swift/Syntax/SyntaxKind.h"
#include "swift/Subsystems.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/SaveAndRestore.h"
+
using namespace swift;
+using namespace swift::syntax;
//===----------------------------------------------------------------------===//
// SILParserState implementation
@@ -1236,7 +1239,7 @@
if (!P.consumeIf(tok::sil_exclamation)) {
// Construct SILDeclRef.
Result = SILDeclRef(VD, Kind, expansion, /*isCurried=*/false, IsObjC);
- if (uncurryLevel < Result.getUncurryLevel())
+ if (uncurryLevel < Result.getParameterListCount() - 1)
Result = Result.asCurried();
return false;
}
@@ -1327,7 +1330,7 @@
// Construct SILDeclRef.
Result = SILDeclRef(VD, Kind, expansion, /*isCurried=*/false, IsObjC);
- if (uncurryLevel < Result.getUncurryLevel())
+ if (uncurryLevel < Result.getParameterListCount() - 1)
Result = Result.asCurried();
return false;
}
@@ -1462,6 +1465,7 @@
if (P.parseList(tok::r_paren, LParenLoc, RParenLoc,
/*AllowSepAfterLast=*/false,
diag::sil_basicblock_arg_rparen,
+ SyntaxKind::Unknown,
[&]() -> ParserStatus {
SILValue Arg;
SourceLoc ArgLoc;
@@ -3735,6 +3739,51 @@
ResultVal = B.createThrow(InstLoc, Val);
break;
}
+ case SILInstructionKind::UnwindInst: {
+ if (parseSILDebugLocation(InstLoc, B))
+ return true;
+ ResultVal = B.createUnwind(InstLoc);
+ break;
+ }
+ case SILInstructionKind::YieldInst: {
+ SmallVector<SILValue, 6> values;
+
+ // Parse a parenthesized (unless length-1), comma-separated list
+ // of yielded values.
+ if (P.consumeIf(tok::l_paren)) {
+ do {
+ if (parseTypedValueRef(Val, B))
+ return true;
+ values.push_back(Val);
+ } while (P.consumeIf(tok::comma));
+
+ if (P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")"))
+ return true;
+
+ } else {
+ if (parseTypedValueRef(Val, B))
+ return true;
+ values.push_back(Val);
+ }
+
+ Identifier resumeName, unwindName;
+ SourceLoc resumeLoc, unwindLoc;
+ if (P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
+ parseVerbatim("resume") ||
+ parseSILIdentifier(resumeName, resumeLoc,
+ diag::expected_sil_block_name) ||
+ P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
+ parseVerbatim("unwind") ||
+ parseSILIdentifier(unwindName, unwindLoc,
+ diag::expected_sil_block_name) ||
+ parseSILDebugLocation(InstLoc, B))
+ return true;
+
+ auto resumeBB = getBBForReference(resumeName, resumeLoc);
+ auto unwindBB = getBBForReference(unwindName, unwindLoc);
+ ResultVal = B.createYield(InstLoc, values, resumeBB, unwindBB);
+ break;
+ }
case SILInstructionKind::BranchInst: {
Identifier BBName;
SourceLoc NameLoc;
diff --git a/lib/SIL/SILArgument.cpp b/lib/SIL/SILArgument.cpp
index dfd1686..87ed4af 100644
--- a/lib/SIL/SILArgument.cpp
+++ b/lib/SIL/SILArgument.cpp
@@ -73,12 +73,14 @@
case TermKind::UnreachableInst:
case TermKind::ReturnInst:
case TermKind::ThrowInst:
+ case TermKind::UnwindInst:
llvm_unreachable("Have terminator that implies no successors?!");
case TermKind::TryApplyInst:
case TermKind::SwitchValueInst:
case TermKind::SwitchEnumAddrInst:
case TermKind::CheckedCastAddrBranchInst:
case TermKind::DynamicMethodBranchInst:
+ case TermKind::YieldInst:
return SILValue();
case TermKind::BranchInst:
return cast<const BranchInst>(TI)->getArg(Index);
diff --git a/lib/SIL/SILBuilder.cpp b/lib/SIL/SILBuilder.cpp
index 06d7bff..aa65f47 100644
--- a/lib/SIL/SILBuilder.cpp
+++ b/lib/SIL/SILBuilder.cpp
@@ -79,8 +79,10 @@
}
auto appliedFnType = SILFunctionType::get(nullptr, extInfo,
+ FTI->getCoroutineKind(),
calleeConvention,
newParams,
+ FTI->getYields(),
results,
FTI->getOptionalErrorResult(),
M.getASTContext());
diff --git a/lib/SIL/SILDeclRef.cpp b/lib/SIL/SILDeclRef.cpp
index 1acb152..65dda5d 100644
--- a/lib/SIL/SILDeclRef.cpp
+++ b/lib/SIL/SILDeclRef.cpp
@@ -227,29 +227,6 @@
return false;
}
-static unsigned getFuncNaturalUncurryLevel(AnyFunctionRef AFR) {
- assert(AFR.getParameterLists().size() >= 1 && "no arguments for func?!");
- return AFR.getParameterLists().size() - 1;
-}
-
-unsigned swift::getNaturalUncurryLevel(ValueDecl *vd) {
- if (auto *func = dyn_cast<FuncDecl>(vd)) {
- return getFuncNaturalUncurryLevel(func);
- } else if (isa<ConstructorDecl>(vd)) {
- return 1;
- } else if (auto *ed = dyn_cast<EnumElementDecl>(vd)) {
- return ed->hasAssociatedValues() ? 1 : 0;
- } else if (isa<DestructorDecl>(vd)) {
- return 0;
- } else if (isa<ClassDecl>(vd)) {
- return 1;
- } else if (isa<VarDecl>(vd)) {
- return 0;
- } else {
- llvm_unreachable("Unhandled ValueDecl for SILDeclRef");
- }
-}
-
SILDeclRef::SILDeclRef(ValueDecl *vd, SILDeclRef::Kind kind,
ResilienceExpansion expansion,
bool isCurried, bool isForeign)
@@ -888,12 +865,23 @@
llvm_unreachable("Unhandled access level in switch.");
}
-unsigned SILDeclRef::getUncurryLevel() const {
- if (isCurried)
- return 0;
- if (!hasDecl())
- return getFuncNaturalUncurryLevel(*getAnyFunctionRef());
- if (kind == Kind::DefaultArgGenerator)
- return 0;
- return getNaturalUncurryLevel(getDecl());
+unsigned SILDeclRef::getParameterListCount() const {
+ if (isCurried || !hasDecl() || kind == Kind::DefaultArgGenerator)
+ return 1;
+
+ auto *vd = getDecl();
+
+ if (auto *func = dyn_cast<AbstractFunctionDecl>(vd)) {
+ return func->getParameterLists().size();
+ } else if (auto *ed = dyn_cast<EnumElementDecl>(vd)) {
+ return ed->hasAssociatedValues() ? 2 : 1;
+ } else if (isa<DestructorDecl>(vd)) {
+ return 1;
+ } else if (isa<ClassDecl>(vd)) {
+ return 2;
+ } else if (isa<VarDecl>(vd)) {
+ return 1;
+ } else {
+ llvm_unreachable("Unhandled ValueDecl for SILDeclRef");
+ }
}
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index 29c2e2e..81f745e 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -196,10 +196,13 @@
type->getWitnessMethodConformanceOrNone() == witnessMethodConformance)
return type;
- return SILFunctionType::get(type->getGenericSignature(), extInfo, callee,
- type->getParameters(), type->getResults(),
+ return SILFunctionType::get(type->getGenericSignature(),
+ extInfo, type->getCoroutineKind(), callee,
+ type->getParameters(), type->getYields(),
+ type->getResults(),
type->getOptionalErrorResult(),
- type->getASTContext(), witnessMethodConformance);
+ type->getASTContext(),
+ witnessMethodConformance);
}
namespace {
@@ -960,7 +963,8 @@
.withIsPseudogeneric(pseudogeneric)
.withNoEscape(extInfo.isNoEscape());
- return SILFunctionType::get(genericSig, silExtInfo, calleeConvention, inputs,
+ return SILFunctionType::get(genericSig, silExtInfo, SILCoroutineKind::None,
+ calleeConvention, inputs, /*yields*/ {},
results, errorResult, M.getASTContext(),
witnessMethodConformance);
}
@@ -1777,7 +1781,7 @@
return false;
// Must be a type member.
- if (constant.getUncurryLevel() != 1)
+ if (constant.getParameterListCount() != 2)
return false;
// Must be imported from a function.
@@ -2235,6 +2239,12 @@
substParams.push_back(subst(origParam));
}
+ SmallVector<SILYieldInfo, 8> substYields;
+ substYields.reserve(origType->getYields().size());
+ for (auto &origYield : origType->getYields()) {
+ substYields.push_back(subst(origYield));
+ }
+
Optional<ProtocolConformanceRef> witnessMethodConformance;
if (auto conformance = origType->getWitnessMethodConformanceOrNone()) {
assert(origType->getExtInfo().hasSelfParam());
@@ -2253,8 +2263,9 @@
}
return SILFunctionType::get(nullptr, origType->getExtInfo(),
+ origType->getCoroutineKind(),
origType->getCalleeConvention(), substParams,
- substResults, substErrorResult,
+ substYields, substResults, substErrorResult,
getASTContext(), witnessMethodConformance);
}
@@ -2267,6 +2278,10 @@
return SILResultInfo(visit(orig.getType()), orig.getConvention());
}
+ SILYieldInfo subst(SILYieldInfo orig) {
+ return SILYieldInfo(visit(orig.getType()), orig.getConvention());
+ }
+
SILParameterInfo subst(SILParameterInfo orig) {
return SILParameterInfo(visit(orig.getType()), orig.getConvention());
}
@@ -2486,7 +2501,7 @@
TypeConverter::LoweredFormalTypes
TypeConverter::getLoweredFormalTypes(SILDeclRef constant,
CanAnyFunctionType fnType) {
- unsigned uncurryLevel = constant.getUncurryLevel();
+ unsigned uncurryLevel = constant.getParameterListCount() - 1;
auto extInfo = fnType->getExtInfo();
// Form an abstraction pattern for bridging purposes.
diff --git a/lib/SIL/SILInstructions.cpp b/lib/SIL/SILInstructions.cpp
index 2af36c2..d7ea5dd 100644
--- a/lib/SIL/SILInstructions.cpp
+++ b/lib/SIL/SILInstructions.cpp
@@ -1056,15 +1056,33 @@
case TermKind::CheckedCastAddrBranchInst:
case TermKind::UnreachableInst:
case TermKind::TryApplyInst:
+ case TermKind::YieldInst:
return false;
case TermKind::ReturnInst:
case TermKind::ThrowInst:
+ case TermKind::UnwindInst:
return true;
}
llvm_unreachable("Unhandled TermKind in switch.");
}
+YieldInst::YieldInst(SILDebugLocation loc, ArrayRef<SILValue> yieldedValues,
+ SILBasicBlock *normalBB, SILBasicBlock *unwindBB)
+ : InstructionBase(loc),
+ DestBBs{{this, normalBB}, {this, unwindBB}},
+ Operands(this, yieldedValues) {}
+
+YieldInst *YieldInst::create(SILDebugLocation loc,
+ ArrayRef<SILValue> yieldedValues,
+ SILBasicBlock *normalBB, SILBasicBlock *unwindBB,
+ SILFunction &F) {
+ void *buffer = F.getModule().allocateInst(sizeof(YieldInst) +
+ decltype(Operands)::getExtraSize(yieldedValues.size()),
+ alignof(YieldInst));
+ return ::new (buffer) YieldInst(loc, yieldedValues, normalBB, unwindBB);
+}
+
BranchInst::BranchInst(SILDebugLocation Loc, SILBasicBlock *DestBB,
ArrayRef<SILValue> Args)
: InstructionBase(Loc), DestBB(this, DestBB),
diff --git a/lib/SIL/SILOwnershipVerifier.cpp b/lib/SIL/SILOwnershipVerifier.cpp
index 8372dce..ecade1b 100644
--- a/lib/SIL/SILOwnershipVerifier.cpp
+++ b/lib/SIL/SILOwnershipVerifier.cpp
@@ -448,6 +448,7 @@
NO_OPERAND_INST(StrongRetainUnowned)
NO_OPERAND_INST(UnownedRetain)
NO_OPERAND_INST(Unreachable)
+NO_OPERAND_INST(Unwind)
#undef NO_OPERAND_INST
/// Instructions whose arguments are always compatible with one convention.
@@ -1109,6 +1110,35 @@
}
OwnershipUseCheckerResult
+OwnershipCompatibilityUseChecker::visitYieldInst(YieldInst *I) {
+ // Indirect return arguments are address types.
+ if (isAddressOrTrivialType())
+ return {compatibleWithOwnership(ValueOwnershipKind::Trivial),
+ UseLifetimeConstraint::MustBeLive};
+
+ auto fnType = I->getFunction()->getLoweredFunctionType();
+ auto yieldInfo = fnType->getYields()[getOperandIndex()];
+ switch (yieldInfo.getConvention()) {
+ case ParameterConvention::Indirect_In:
+ case ParameterConvention::Direct_Owned:
+ return visitApplyParameter(ValueOwnershipKind::Owned,
+ UseLifetimeConstraint::MustBeInvalidated);
+ case ParameterConvention::Indirect_In_Constant:
+ case ParameterConvention::Direct_Unowned:
+ // We accept unowned, owned, and guaranteed in unowned positions.
+ return {true, UseLifetimeConstraint::MustBeLive};
+ case ParameterConvention::Indirect_In_Guaranteed:
+ case ParameterConvention::Direct_Guaranteed:
+ return visitApplyParameter(ValueOwnershipKind::Guaranteed,
+ UseLifetimeConstraint::MustBeLive);
+ // The following conventions should take address types.
+ case ParameterConvention::Indirect_Inout:
+ case ParameterConvention::Indirect_InoutAliasable:
+ llvm_unreachable("Unexpected non-trivial parameter convention.");
+ }
+}
+
+OwnershipUseCheckerResult
OwnershipCompatibilityUseChecker::visitAssignInst(AssignInst *I) {
if (getValue() == I->getSrc()) {
if (isAddressOrTrivialType()) {
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index a4dacb1..541c479 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -351,7 +351,7 @@
break;
}
- auto uncurryLevel = getUncurryLevel();
+ auto uncurryLevel = getParameterListCount() - 1;
if (uncurryLevel != 0)
OS << (isDot ? '.' : '!') << uncurryLevel;
@@ -1854,6 +1854,21 @@
*this << getIDAndType(TI->getOperand());
}
+ void visitUnwindInst(UnwindInst *UI) {
+ // no operands
+ }
+
+ void visitYieldInst(YieldInst *YI) {
+ auto values = YI->getYieldedValues();
+ if (values.size() != 1) *this << '(';
+ interleave(values,
+ [&](SILValue value) { *this << getIDAndType(value); },
+ [&] { *this << ", "; });
+ if (values.size() != 1) *this << ')';
+ *this << ", resume " << Ctx.getID(YI->getResumeBB())
+ << ", unwind " << Ctx.getID(YI->getUnwindBB());
+ }
+
void visitSwitchValueInst(SwitchValueInst *SII) {
*this << getIDAndType(SII->getOperand());
for (unsigned i = 0, e = SII->getNumCases(); i < e; ++i) {
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index 7252575..f3630bf 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -941,6 +941,9 @@
"apply instruction cannot call function with error result");
}
+ require(!calleeConv.funcTy->isCoroutine(),
+ "cannot call coroutine with normal apply");
+
// Check that if the apply is of a noreturn callee, make sure that an
// unreachable is the next instruction.
if (AI->getModule().getStage() == SILStage::Raw ||
@@ -955,6 +958,9 @@
SILFunctionConventions calleeConv(AI->getSubstCalleeType(), F.getModule());
+ require(!calleeConv.funcTy->isCoroutine(),
+ "cannot call coroutine with normal apply");
+
auto normalBB = AI->getNormalBB();
require(normalBB->args_size() == 1,
"normal destination of try_apply must take one argument");
@@ -2164,6 +2170,8 @@
auto constantInfo = F.getModule().Types.getConstantInfo(method);
auto methodTy = constantInfo.SILFnType;
+ assert(!methodTy->isCoroutine());
+
// Map interface types to archetypes.
if (auto *env = constantInfo.GenericEnv) {
auto subs = env->getForwardingSubstitutions();
@@ -2196,8 +2204,10 @@
auto fnTy = SILFunctionType::get(nullptr,
methodTy->getExtInfo(),
+ methodTy->getCoroutineKind(),
methodTy->getCalleeConvention(),
dynParams,
+ methodTy->getYields(),
dynResults,
methodTy->getOptionalErrorResult(),
F.getASTContext());
@@ -3309,6 +3319,35 @@
"throw operand type does not match error result type of function");
}
+ void checkUnwindInst(UnwindInst *UI) {
+ require(F.getLoweredFunctionType()->isCoroutine(),
+ "unwind in non-coroutine function");
+ }
+
+ void checkYieldInst(YieldInst *YI) {
+ CanSILFunctionType fnType = F.getLoweredFunctionType();
+ require(fnType->isCoroutine(),
+ "yield in non-coroutine function");
+
+ auto yieldedValues = YI->getYieldedValues();
+ auto yieldInfos = fnType->getYields();
+ require(yieldedValues.size() == yieldInfos.size(),
+ "wrong number of yielded values for function");
+ for (auto i : indices(yieldedValues)) {
+ SILType yieldType =
+ F.mapTypeIntoContext(fnConv.getSILType(yieldInfos[i]));
+ require(yieldedValues[i]->getType() == yieldType,
+ "yielded value does not match yield type of coroutine");
+ }
+
+ // We require the resume and unwind destinations to be unique in order
+ // to prevent either edge from becoming critical.
+ require(YI->getResumeBB()->getSinglePredecessorBlock(),
+ "resume dest of 'yield' must be uniquely used");
+ require(YI->getUnwindBB()->getSinglePredecessorBlock(),
+ "unwind dest of 'yield' must be uniquely used");
+ }
+
void checkSelectEnumCases(SelectEnumInstBase *I) {
EnumDecl *eDecl = I->getEnumOperand()->getType().getEnumOrBoundGenericEnum();
require(eDecl, "select_enum operand must be an enum");
@@ -4147,9 +4186,18 @@
/// - accesses must be uniquely ended
/// - flow-sensitive states must be equivalent on all paths into a block
void verifyFlowSensitiveRules(SILFunction *F) {
+ enum CFGState {
+ /// No special rules are in play.
+ Normal,
+ /// We've followed the resume edge of a yield in a yield_once coroutine.
+ YieldOnceResume,
+ /// We've followed the unwind edge of a yield.
+ YieldUnwind
+ };
struct BBState {
std::vector<SingleValueInstruction*> Stack;
std::set<BeginAccessInst*> Accesses;
+ CFGState CFG = Normal;
};
// Do a breath-first search through the basic blocks.
@@ -4195,6 +4243,29 @@
"return with stack allocs that haven't been deallocated");
require(state.Accesses.empty(),
"return with accesses that haven't been ended");
+
+ if (isa<UnwindInst>(term)) {
+ require(state.CFG == YieldUnwind,
+ "encountered 'unwind' when not on unwind path");
+ } else {
+ require(state.CFG != YieldUnwind,
+ "encountered 'return' or 'throw' when on unwind path");
+ if (isa<ReturnInst>(term) &&
+ F->getLoweredFunctionType()->getCoroutineKind() ==
+ SILCoroutineKind::YieldOnce &&
+ F->getModule().getStage() != SILStage::Raw) {
+ require(state.CFG == YieldOnceResume,
+ "encountered 'return' before yielding a value in "
+ "yield_once coroutine");
+ }
+ }
+ }
+
+ if (isa<YieldInst>(term)) {
+ require(state.CFG != YieldOnceResume,
+ "encountered multiple 'yield's along single path");
+ require(state.CFG == Normal,
+ "encountered 'yield' on abnormal CFG path");
}
auto successors = term->getSuccessors();
@@ -4215,9 +4286,30 @@
// worklist and continue.
if (insertResult.second) {
Worklist.push_back(succBB);
+
+ // If we're following a 'yield', update the CFG state:
+ if (isa<YieldInst>(term)) {
+ // Enforce that the unwind logic is segregated in all stages.
+ if (i == 1) {
+ insertResult.first->second.CFG = YieldUnwind;
+
+ // We check the yield_once rule in the mandatory analyses,
+ // so we can't assert it yet in the raw stage.
+ } else if (F->getLoweredFunctionType()->getCoroutineKind()
+ == SILCoroutineKind::YieldOnce &&
+ F->getModule().getStage() != SILStage::Raw) {
+ insertResult.first->second.CFG = YieldOnceResume;
+ }
+ }
+
continue;
}
+ // This rule is checked elsewhere, but we'd want to assert it
+ // here anyway.
+ require(!isa<YieldInst>(term),
+ "successor of 'yield' should not be encountered twice");
+
// Check that the stack height is consistent coming from all entry
// points into this BB. We only care about consistency if there is
// a possible return from this function along the path starting at
@@ -4233,6 +4325,8 @@
"inconsistent stack heights entering basic block");
require(state.Accesses == foundState.Accesses || isUnreachable(),
"inconsistent access sets entering basic block");
+ require(state.CFG == foundState.CFG,
+ "inconsistent coroutine states entering basic block");
}
}
}
diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp
index da1b89c..9cfd5e6 100644
--- a/lib/SIL/TypeLowering.cpp
+++ b/lib/SIL/TypeLowering.cpp
@@ -2107,9 +2107,9 @@
if (genericSig && genericSig->areAllParamsConcrete())
genericSig = nullptr;
- return SILFunctionType::get(genericSig, extInfo,
+ return SILFunctionType::get(genericSig, extInfo, SILCoroutineKind::None,
/*callee*/ ParameterConvention::Direct_Unowned,
- params, results, None, ctx,
+ params, {}, results, None, ctx,
witnessMethodConformance);
}
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index bb4e271..d182a49 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -432,8 +432,9 @@
};
CanSILFunctionType topLevelType = SILFunctionType::get(nullptr, extInfo,
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
- params,
+ params, /*yields*/ {},
SILResultInfo(Int32Ty,
ResultConvention::Unowned),
None,
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index 71395d6..d269ad8 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -64,16 +64,6 @@
llvm_unreachable("bad representation");
}
-static CanType getDynamicMethodSelfType(SILGenFunction &SGF,
- const ArgumentSource &proto,
- ValueDecl *member) {
- if (member->isInstanceMember()) {
- return SGF.getASTContext().getAnyObjectType();
- } else {
- return proto.getSILSubstType(SGF).getSwiftRValueType();
- }
-}
-
/// Return the formal type for the partial-apply result type of a
/// dynamic method invocation.
static CanFunctionType
@@ -113,37 +103,6 @@
return fnType;
}
-/// Replace the 'self' parameter in the given type.
-static CanSILFunctionType
-replaceSelfTypeForDynamicLookup(ASTContext &ctx,
- CanSILFunctionType fnType,
- CanType newSelfType,
- SILDeclRef methodName) {
- auto oldParams = fnType->getParameters();
- SmallVector<SILParameterInfo, 4> newParams;
- newParams.append(oldParams.begin(), oldParams.end() - 1);
- newParams.push_back({newSelfType, oldParams.back().getConvention()});
-
- // If the method returns Self, substitute AnyObject for the result type.
- SmallVector<SILResultInfo, 4> newResults;
- newResults.append(fnType->getResults().begin(), fnType->getResults().end());
- if (auto fnDecl = dyn_cast<FuncDecl>(methodName.getDecl())) {
- if (fnDecl->hasDynamicSelf()) {
- auto anyObjectTy = ctx.getAnyObjectType();
- for (auto &result : newResults) {
- auto newResultTy
- = result.getType()->replaceCovariantResultType(anyObjectTy, 0);
- result = result.getWithType(newResultTy->getCanonicalType());
- }
- }
- }
-
- return SILFunctionType::get(nullptr, fnType->getExtInfo(),
- fnType->getCalleeConvention(), newParams,
- newResults, fnType->getOptionalErrorResult(), ctx,
- fnType->getWitnessMethodConformanceOrNone());
-}
-
/// Retrieve the type to use for a method found via dynamic lookup.
static CanSILFunctionType
getDynamicMethodLoweredType(SILGenFunction &SGF, SILValue v,
@@ -161,7 +120,7 @@
auto methodTy = SGF.SGM.M.Types
.getUncachedSILFunctionTypeForConstant(methodName, objcFormalTy);
- return replaceSelfTypeForDynamicLookup(ctx, methodTy, selfTy, methodName);
+ return methodTy;
}
/// Check if we can perform a dynamic dispatch on a super method call.
@@ -398,13 +357,11 @@
}
static Callee forDynamic(SILGenFunction &SGF, ArgumentSource &&arg,
SILDeclRef c, const SubstitutionList &constantSubs,
- CanAnyFunctionType partialSubstFormalType,
+ CanAnyFunctionType substFormalType,
SubstitutionList subs, SILLocation l) {
auto &ci = SGF.getConstantInfo(c);
AbstractionPattern origFormalType = ci.FormalPattern;
- auto selfType = getDynamicMethodSelfType(SGF, arg, c.getDecl());
-
// Replace the original self type with the partially-applied subst type.
auto origFormalFnType = cast<AnyFunctionType>(origFormalType.getType());
if (auto genericFnType = dyn_cast<GenericFunctionType>(origFormalFnType)) {
@@ -418,16 +375,8 @@
cast<FunctionType>(genericFnType->substGenericArgs(constantSubs)
->getCanonicalType());
}
- origFormalFnType = CanFunctionType::get(selfType,
- origFormalFnType.getResult(),
- origFormalFnType->getExtInfo());
origFormalType.rewriteType(CanGenericSignature(), origFormalFnType);
- // Add the self type clause to the partially-applied subst type.
- auto substFormalType = CanFunctionType::get(selfType,
- partialSubstFormalType,
- origFormalFnType->getExtInfo());
-
return Callee(Kind::DynamicMethod, SGF, std::move(arg), c, origFormalType,
substFormalType, subs, l);
}
@@ -457,10 +406,10 @@
return SubstFormalInterfaceType;
}
- unsigned getNaturalUncurryLevel() const {
+ unsigned getParameterListCount() const {
switch (kind) {
case Kind::IndirectValue:
- return 0;
+ return 1;
case Kind::StandaloneFunction:
case Kind::EnumElement:
@@ -468,7 +417,7 @@
case Kind::SuperMethod:
case Kind::WitnessMethod:
case Kind::DynamicMethod:
- return Constant.getUncurryLevel();
+ return Constant.getParameterListCount();
}
llvm_unreachable("Unhandled Kind in switch.");
@@ -498,21 +447,52 @@
return result;
}
- ManagedValue getFnValueAtUncurryLevel(SILGenFunction &SGF,
- unsigned level) const & {
+ SILDeclRef getCurriedConstant(bool isCurried) const {
+ if (isCurried) {
+ auto constant = Constant.asCurried();
+
+ // If we're currying a direct reference to a class-dispatched method,
+ // make sure we emit the right set of thunks.
+ if (kind == Kind::StandaloneFunction) {
+ if (auto func = Constant.getAbstractFunctionDecl()) {
+ if (getMethodDispatch(func) == MethodDispatch::Class) {
+ return constant.asDirectReference(true);
+ }
+ }
+ }
+
+ return constant;
+ }
+
+ return Constant;
+ }
+
+ SILType getDynamicMethodType(SILModule &M) const {
+ // Lower the substituted type from the AST, which should have any generic
+ // parameters in the original signature erased to their upper bounds.
+ auto substFormalType = getSubstFormalType();
+ auto objcFormalType = substFormalType.withExtInfo(
+ substFormalType->getExtInfo().withSILRepresentation(
+ SILFunctionTypeRepresentation::ObjCMethod));
+ auto fnType = M.Types.getUncachedSILFunctionTypeForConstant(
+ Constant, objcFormalType);
+
+ return SILType::getPrimitiveObjectType(fnType);
+ }
+
+ ManagedValue getFnValue(SILGenFunction &SGF, bool isCurried) const & {
Optional<SILDeclRef> constant = None;
if (!Constant) {
- assert(level == 0 && "can't curry indirect function");
+ assert(!isCurried && "can't curry indirect function");
} else {
- unsigned uncurryLevel = Constant.getUncurryLevel();
- assert(level <= uncurryLevel &&
- "uncurrying past natural uncurry level of standalone function");
- if (level < uncurryLevel) {
- assert(level == 0);
- constant = Constant.asCurried();
- } else {
- constant = Constant;
+ constant = getCurriedConstant(isCurried);
+
+ // If the call is curried, emit a direct call to the curry thunk.
+ if (constant->isCurried) {
+ auto constantInfo = SGF.getConstantInfo(*constant);
+ SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
+ return ManagedValue::forUnmanaged(ref);
}
}
@@ -522,36 +502,13 @@
return IndirectValue;
case Kind::StandaloneFunction: {
- // If we're currying a direct reference to a class-dispatched method,
- // make sure we emit the right set of thunks.
- if (constant->isCurried && Constant.hasDecl())
- if (auto func = Constant.getAbstractFunctionDecl())
- if (getMethodDispatch(func) == MethodDispatch::Class)
- constant = constant->asDirectReference(true);
-
auto constantInfo = SGF.getConstantInfo(*constant);
SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
return ManagedValue::forUnmanaged(ref);
}
- case Kind::EnumElement: {
- auto constantInfo = SGF.getConstantInfo(*constant);
-
- // We should not end up here if the enum constructor call is fully
- // applied.
- assert(constant->isCurried);
-
- SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
- return ManagedValue::forUnmanaged(ref);
- }
+ case Kind::EnumElement:
+ llvm_unreachable("Should have been curried");
case Kind::ClassMethod: {
- auto constantInfo = SGF.getConstantInfo(*constant);
-
- // If the call is curried, emit a direct call to the curry thunk.
- if (constant->isCurried) {
- SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
- return ManagedValue::forUnmanaged(ref);
- }
-
auto methodTy = SGF.SGM.Types.getConstantOverrideType(*constant);
// Otherwise, do the dynamic dispatch inline.
@@ -594,15 +551,8 @@
case Kind::WitnessMethod: {
auto constantInfo = SGF.getConstantInfo(*constant);
- // If the call is curried, emit a direct call to the curry thunk.
- if (constant->isCurried) {
- SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
- return ManagedValue::forUnmanaged(ref);
- }
-
- auto proto = Constant.getDecl()
- ->getDeclContext()
- ->getAsProtocolOrProtocolExtensionContext();
+ auto proto = cast<ProtocolDecl>(
+ Constant.getDecl()->getDeclContext());
auto lookupType = getSubstFormalType()
.getInput()
->getRValueInstanceType()
@@ -612,52 +562,34 @@
Loc, lookupType, ProtocolConformanceRef(proto), *constant,
constantInfo.getSILType(), constant->isForeign);
return ManagedValue::forUnmanaged(fn);
- ;
}
case Kind::DynamicMethod: {
- assert(!constant->isCurried);
assert(constant->isForeign);
-
- // Lower the substituted type from the AST, which should have any generic
- // parameters in the original signature erased to their upper bounds.
- auto substFormalType = getSubstFormalType();
- auto objcFormalType = substFormalType.withExtInfo(
- substFormalType->getExtInfo().withSILRepresentation(
- SILFunctionTypeRepresentation::ObjCMethod));
- auto fnType = SGF.SGM.M.Types.getUncachedSILFunctionTypeForConstant(
- *constant, objcFormalType);
-
- auto closureType = replaceSelfTypeForDynamicLookup(
- SGF.getASTContext(), fnType,
- SelfValue.getValue().getSILSubstType(SGF).getSwiftRValueType(),
- Constant);
+ auto closureType = getDynamicMethodType(SGF.SGM.M);
Scope S(SGF, Loc);
ManagedValue self =
SelfValue.getValue().borrow(SGF).getAsSingleValue(SGF);
SILValue fn = SGF.B.createObjCMethod(
Loc, self.getValue(), *constant,
- SILType::getPrimitiveObjectType(closureType));
+ closureType);
return ManagedValue::forUnmanaged(fn);
}
}
}
- CalleeTypeInfo getTypeInfoAtUncurryLevel(SILGenFunction &SGF,
- unsigned level) const & {
+ CalleeTypeInfo getTypeInfo(SILGenFunction &SGF, bool isCurried) const & {
Optional<SILDeclRef> constant = None;
if (!Constant) {
- assert(level == 0 && "can't curry indirect function");
+ assert(!isCurried && "can't curry indirect function");
} else {
- unsigned uncurryLevel = Constant.getUncurryLevel();
- assert(level <= uncurryLevel &&
- "uncurrying past natural uncurry level of standalone function");
- if (level < uncurryLevel) {
- assert(level == 0);
- constant = Constant.asCurried();
- } else {
- constant = Constant;
+ constant = getCurriedConstant(isCurried);
+
+ // If the call is curried, emit a direct call to the curry thunk.
+ if (constant->isCurried) {
+ auto constantInfo = SGF.getConstantInfo(*constant);
+ return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
}
}
@@ -667,38 +599,16 @@
return createCalleeTypeInfo(SGF, constant, IndirectValue.getType());
case Kind::StandaloneFunction: {
- // If we're currying a direct reference to a class-dispatched method,
- // make sure we emit the right set of thunks.
- if (constant->isCurried && Constant.hasDecl())
- if (auto func = Constant.getAbstractFunctionDecl())
- if (getMethodDispatch(func) == MethodDispatch::Class)
- constant = constant->asDirectReference(true);
-
auto constantInfo = SGF.getConstantInfo(*constant);
return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
- ;
}
- case Kind::EnumElement: {
- auto constantInfo = SGF.getConstantInfo(*constant);
-
- // We should not end up here if the enum constructor call is fully
- // applied.
- assert(constant->isCurried);
- return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
- }
+ case Kind::EnumElement:
+ llvm_unreachable("Should have been curried");
case Kind::ClassMethod: {
- // If the call is curried, emit a direct call to the curry thunk.
- if (constant->isCurried) {
- auto constantInfo = SGF.getConstantInfo(*constant);
- return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
- }
-
- // Otherwise, grab the override info.
auto constantInfo = SGF.SGM.Types.getConstantOverrideInfo(*constant);
return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
}
case Kind::SuperMethod: {
- assert(!constant->isCurried);
auto base = SGF.SGM.Types.getOverriddenVTableEntry(*constant);
auto constantInfo =
SGF.SGM.Types.getConstantOverrideInfo(*constant, base);
@@ -709,23 +619,7 @@
return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
}
case Kind::DynamicMethod: {
- assert(!constant->isCurried);
-
- // Lower the substituted type from the AST, which should have any generic
- // parameters in the original signature erased to their upper bounds.
- auto substFormalType = getSubstFormalType();
- auto objcFormalType = substFormalType.withExtInfo(
- substFormalType->getExtInfo().withSILRepresentation(
- SILFunctionTypeRepresentation::ObjCMethod));
- auto fnType = SGF.SGM.M.Types.getUncachedSILFunctionTypeForConstant(
- *constant, objcFormalType);
-
- auto closureType = replaceSelfTypeForDynamicLookup(
- SGF.getASTContext(), fnType,
- SelfValue.getValue().getSILSubstType(SGF).getSwiftRValueType(),
- Constant);
-
- SILType formalType = SILType::getPrimitiveObjectType(closureType);
+ auto formalType = getDynamicMethodType(SGF.SGM.M);
return createCalleeTypeInfo(SGF, constant, formalType);
}
}
@@ -743,11 +637,7 @@
/// lowering, such as a builtin, or return null if there is no specialized
/// emitter.
Optional<SpecializedEmitter>
- getSpecializedEmitter(SILGenModule &SGM, unsigned uncurryLevel) const {
- // Currently we have no curried known functions.
- if (uncurryLevel != 0)
- return None;
-
+ getSpecializedEmitter(SILGenModule &SGM) const {
switch (kind) {
case Kind::StandaloneFunction: {
return SpecializedEmitter::forDecl(SGM, Constant);
@@ -1515,6 +1405,10 @@
auto substFormalType =
cast<FunctionType>(dynamicMemberRef->getType()->getCanonicalType()
.getAnyOptionalObjectType());
+ substFormalType = CanFunctionType::get(
+ dynamicMemberRef->getBase()->getType()->getCanonicalType(),
+ substFormalType, AnyFunctionType::ExtInfo());
+
setCallee(Callee::forDynamic(SGF, baseArgSource.delayedBorrow(SGF),
member, memberRef.getSubstitutions(),
substFormalType, {}, e));
@@ -3957,8 +3851,7 @@
std::vector<CallSite> extraSites;
Callee callee;
FormalEvaluationScope initialWritebackScope;
- unsigned uncurries;
- bool applied;
+ unsigned expectedSiteCount;
bool assumedPlusZeroSelf;
public:
@@ -3968,17 +3861,14 @@
bool assumedPlusZeroSelf = false)
: SGF(SGF), callee(std::move(callee)),
initialWritebackScope(std::move(writebackScope)),
- uncurries(callee.getNaturalUncurryLevel() + 1), applied(false),
+ expectedSiteCount(callee.getParameterListCount()),
assumedPlusZeroSelf(assumedPlusZeroSelf) {}
/// Add a level of function application by passing in its possibly
/// unevaluated arguments and their formal type.
void addCallSite(CallSite &&site) {
- assert(!applied && "already applied!");
-
// Append to the main argument list if we have uncurry levels remaining.
- if (uncurries > 0) {
- --uncurries;
+ if (uncurriedSites.size() < expectedSiteCount) {
uncurriedSites.push_back(std::move(site));
return;
}
@@ -4009,30 +3899,21 @@
/// Is this a fully-applied enum element constructor call?
bool isEnumElementConstructor() {
- return (callee.kind == Callee::Kind::EnumElement && uncurries == 0);
+ return (callee.kind == Callee::Kind::EnumElement &&
+ uncurriedSites.size() == expectedSiteCount);
}
/// True if this is a completely unapplied super method call
- bool isPartiallyAppliedSuperMethod(unsigned uncurryLevel) {
+ bool isPartiallyAppliedSuperMethod() {
return (callee.kind == Callee::Kind::SuperMethod &&
- uncurryLevel == 0);
+ uncurriedSites.size() == 1);
}
RValue apply(SGFContext C = SGFContext()) {
initialWritebackScope.verify();
- assert(!applied && "already applied!");
-
- applied = true;
-
- // Get the callee value at the needed uncurry level, uncurrying as
- // much as possible. If the number of calls is less than the natural
- // uncurry level, the callee emission might create a curry thunk.
- unsigned uncurryLevel = callee.getNaturalUncurryLevel() - uncurries;
-
// Emit the first level of call.
- FirstLevelApplicationResult firstLevelResult =
- applyFirstLevelCallee(uncurryLevel, C);
+ auto firstLevelResult = applyFirstLevelCallee(C);
// End of the initial writeback scope.
initialWritebackScope.verify();
@@ -4061,17 +3942,8 @@
firstLevelResult.foreignSelf, C, formalTypeThrows);
}
- ~CallEmission() { assert(applied && "never applied!"); }
-
// Movable, but not copyable.
- CallEmission(CallEmission &&e)
- : SGF(e.SGF), uncurriedSites(std::move(e.uncurriedSites)),
- extraSites(std::move(e.extraSites)), callee(std::move(e.callee)),
- initialWritebackScope(std::move(e.initialWritebackScope)),
- uncurries(e.uncurries), applied(e.applied),
- assumedPlusZeroSelf(e.assumedPlusZeroSelf) {
- e.applied = true;
- }
+ CallEmission(CallEmission &&e) = default;
private:
CallEmission(const CallEmission &) = delete;
@@ -4130,19 +4002,17 @@
FirstLevelApplicationResult
applySpecializedEmitter(SpecializedEmitter &specializedEmitter,
- unsigned uncurryLevel, SGFContext C);
+ SGFContext C);
FirstLevelApplicationResult
- applyPartiallyAppliedSuperMethod(unsigned uncurryLevel, SGFContext C);
+ applyPartiallyAppliedSuperMethod(SGFContext C);
FirstLevelApplicationResult
- applyEnumElementConstructor(unsigned uncurryLevel, SGFContext C);
+ applyEnumElementConstructor(SGFContext C);
- FirstLevelApplicationResult applyNormalCall(unsigned uncurryLevel,
- SGFContext C);
+ FirstLevelApplicationResult applyNormalCall(SGFContext C);
- FirstLevelApplicationResult applyFirstLevelCallee(unsigned uncurryLevel,
- SGFContext C);
+ FirstLevelApplicationResult applyFirstLevelCallee(SGFContext C);
RValue applyRemainingCallSites(RValue &&result,
AbstractionPattern origFormalType,
@@ -4165,25 +4035,27 @@
}
CallEmission::FirstLevelApplicationResult
-CallEmission::applyFirstLevelCallee(unsigned uncurryLevel, SGFContext C) {
+CallEmission::applyFirstLevelCallee(SGFContext C) {
// Check for a specialized emitter.
- if (auto emitter = callee.getSpecializedEmitter(SGF.SGM, uncurryLevel)) {
- return applySpecializedEmitter(emitter.getValue(), uncurryLevel, C);
+ if (uncurriedSites.size() == expectedSiteCount) {
+ if (auto emitter = callee.getSpecializedEmitter(SGF.SGM)) {
+ return applySpecializedEmitter(emitter.getValue(), C);
+ }
}
- if (isPartiallyAppliedSuperMethod(uncurryLevel)) {
- return applyPartiallyAppliedSuperMethod(uncurryLevel, C);
+ if (isPartiallyAppliedSuperMethod()) {
+ return applyPartiallyAppliedSuperMethod(C);
}
if (isEnumElementConstructor()) {
- return applyEnumElementConstructor(uncurryLevel, C);
+ return applyEnumElementConstructor(C);
}
- return applyNormalCall(uncurryLevel, C);
+ return applyNormalCall(C);
}
CallEmission::FirstLevelApplicationResult
-CallEmission::applyNormalCall(unsigned uncurryLevel, SGFContext C) {
+CallEmission::applyNormalCall(SGFContext C) {
FirstLevelApplicationResult firstLevelResult;
// We use the context emit-into initialization only for the
@@ -4193,16 +4065,16 @@
firstLevelResult.formalType = callee.getSubstFormalType();
auto origFormalType = callee.getOrigFormalType();
+ bool isCurried = (uncurriedSites.size() < callee.getParameterListCount());
+
// Get the callee type information.
- CalleeTypeInfo calleeTypeInfo =
- callee.getTypeInfoAtUncurryLevel(SGF, uncurryLevel);
- ManagedValue mv = callee.getFnValueAtUncurryLevel(SGF, uncurryLevel);
+ auto calleeTypeInfo = callee.getTypeInfo(SGF, isCurried);
+ auto mv = callee.getFnValue(SGF, isCurried);
// In C language modes, substitute the type of the AbstractionPattern
// so that we won't see type parameters down when we try to form bridging
// conversions.
- CanSILFunctionType calleeFnTy = mv.getType().castTo<SILFunctionType>();
- if (calleeFnTy->getLanguage() == SILFunctionLanguage::C) {
+ if (calleeTypeInfo.substFnType->getLanguage() == SILFunctionLanguage::C) {
if (auto genericFnType =
dyn_cast<GenericFunctionType>(origFormalType.getType())) {
auto fnType = genericFnType->substGenericArgs(callee.getSubstitutions());
@@ -4255,7 +4127,7 @@
}
CallEmission::FirstLevelApplicationResult
-CallEmission::applyEnumElementConstructor(unsigned uncurryLevel, SGFContext C) {
+CallEmission::applyEnumElementConstructor(SGFContext C) {
FirstLevelApplicationResult firstLevelResult;
assert(!assumedPlusZeroSelf);
SGFContext uncurriedContext = (extraSites.empty() ? C : SGFContext());
@@ -4310,10 +4182,8 @@
}
CallEmission::FirstLevelApplicationResult
-CallEmission::applyPartiallyAppliedSuperMethod(unsigned uncurryLevel,
- SGFContext C) {
+CallEmission::applyPartiallyAppliedSuperMethod(SGFContext C) {
FirstLevelApplicationResult firstLevelResult;
- assert(uncurryLevel == 0);
// We want to emit the arguments as fully-substituted values
// because that's what the partially applied super method expects;
@@ -4393,7 +4263,7 @@
CallEmission::FirstLevelApplicationResult
CallEmission::applySpecializedEmitter(SpecializedEmitter &specializedEmitter,
- unsigned uncurryLevel, SGFContext C) {
+ SGFContext C) {
FirstLevelApplicationResult firstLevelResult;
// We use the context emit-into initialization only for the
@@ -4402,8 +4272,6 @@
ManagedValue mv;
- assert(uncurryLevel == 0);
-
// Get the callee type information. We want to emit the arguments as
// fully-substituted values because that's what the specialized emitters
// expect.
@@ -4686,8 +4554,8 @@
auto origFormalType = callee.getOrigFormalType();
auto substFormalType = callee.getSubstFormalType();
- CalleeTypeInfo calleeTypeInfo = callee.getTypeInfoAtUncurryLevel(*this, 0);
- ManagedValue mv = callee.getFnValueAtUncurryLevel(*this, 0);
+ auto calleeTypeInfo = callee.getTypeInfo(*this, /*isCurried=*/false);
+ auto mv = callee.getFnValue(*this, /*isCurried=*/false);
assert(!calleeTypeInfo.foreignError);
assert(!calleeTypeInfo.foreignSelf.isImportAsMember());
diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp
index f3a4cc2..c48ce35 100644
--- a/lib/SILGen/SILGenBridging.cpp
+++ b/lib/SILGen/SILGenBridging.cpp
@@ -498,6 +498,8 @@
auto blockInterfaceTy = cast<SILFunctionType>(
F.mapTypeOutOfContext(loweredBlockTy)->getCanonicalType());
+ assert(!blockInterfaceTy->isCoroutine());
+
auto storageTy = SILBlockStorageType::get(loweredFuncTy);
auto storageInterfaceTy = SILBlockStorageType::get(fnInterfaceTy);
@@ -535,8 +537,9 @@
}
auto invokeTy = SILFunctionType::get(
- genericSig, extInfo, ParameterConvention::Direct_Unowned, params,
- blockInterfaceTy->getResults(),
+ genericSig, extInfo, SILCoroutineKind::None,
+ ParameterConvention::Direct_Unowned, params,
+ /*yields*/ {}, blockInterfaceTy->getResults(),
blockInterfaceTy->getOptionalErrorResult(), getASTContext());
// Create the invoke function. Borrow the mangling scheme from reabstraction
diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp
index f782af6..d08ad65 100644
--- a/lib/SILGen/SILGenConstructor.cpp
+++ b/lib/SILGen/SILGenConstructor.cpp
@@ -857,8 +857,10 @@
initConstantTy = SILFunctionType::get(initConstantTy->getGenericSignature(),
initConstantTy->getExtInfo(),
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
param,
+ /*yields*/ {},
result,
// TODO: throwing initializer?
None,
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 0528044..a0f3f0e 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -1042,8 +1042,11 @@
// If the referenced decl isn't a VarDecl, it should be a constant of some
// sort.
SILDeclRef silDeclRef(decl);
- if (silDeclRef.getUncurryLevel() > 0)
+ if (silDeclRef.getParameterListCount() == 2) {
+ // Unqualified reference to an instance method from a static context,
+ // without applying 'self'.
silDeclRef = silDeclRef.asCurried();
+ }
ManagedValue result = emitClosureValue(loc, silDeclRef, refType,
declRef.getSubstitutions());
@@ -3029,8 +3032,9 @@
SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
/*pseudogeneric*/ false,
/*noescape*/ false),
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
- params, result, None, SGF.getASTContext());
+ params, {}, result, None, SGF.getASTContext());
// Find the function and see if we already created it.
SmallVector<CanType, 2> interfaceSubs;
@@ -3149,8 +3153,9 @@
SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
/*pseudogeneric*/ false,
/*noescape*/ false),
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
- params, {}, None, SGF.getASTContext());
+ params, {}, {}, None, SGF.getASTContext());
// Mangle the name of the thunk to see if we already created it.
SmallString<64> nameBuf;
@@ -3317,8 +3322,9 @@
SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
/*pseudogeneric*/ false,
/*noescape*/ false),
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
- params, results, None, C);
+ params, /*yields*/ {}, results, None, C);
// Mangle the name of the thunk to see if we already created it.
SmallString<64> nameBuf;
@@ -3483,8 +3489,9 @@
SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
/*pseudogeneric*/ false,
/*noescape*/ false),
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
- params, results, None, C);
+ params, /*yields*/ {}, results, None, C);
// Mangle the name of the thunk to see if we already created it.
SmallString<64> nameBuf;
diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp
index 8844bc6..f579dcc 100644
--- a/lib/SILGen/SILGenFunction.cpp
+++ b/lib/SILGen/SILGenFunction.cpp
@@ -475,9 +475,11 @@
SILFunctionType::ExtInfo()
.withRepresentation(SILFunctionType::Representation::
CFunctionPointer),
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
SILParameterInfo(anyObjectMetaTy,
ParameterConvention::Direct_Unowned),
+ /*yields*/ {},
SILResultInfo(OptNSStringTy,
ResultConvention::Autoreleased),
/*error result*/ None,
@@ -577,8 +579,10 @@
// Should be C calling convention, but NSApplicationMain
// has an overlay to fix the type of argv.
.withRepresentation(SILFunctionType::Representation::Thin),
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
argTypes,
+ /*yields*/ {},
SILResultInfo(argc->getType().getSwiftRValueType(),
ResultConvention::Unowned),
/*error result*/ None,
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index 4cd88e0..33dc4ec 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -2837,6 +2837,15 @@
param.getConvention()));
}
+ SmallVector<SILYieldInfo, 4> interfaceYields;
+ for (auto &yield : expectedType->getYields()) {
+ auto yieldIfaceTy = GenericEnvironment::mapTypeOutOfContext(
+ genericEnv, yield.getType());
+ auto interfaceYield =
+ yield.getWithType(yieldIfaceTy->getCanonicalType(genericSig));
+ interfaceYields.push_back(interfaceYield);
+ }
+
SmallVector<SILResultInfo, 4> interfaceResults;
for (auto &result : expectedType->getResults()) {
auto resultIfaceTy = GenericEnvironment::mapTypeOutOfContext(
@@ -2858,9 +2867,10 @@
// The type of the thunk function.
return SILFunctionType::get(genericSig, extInfo,
+ expectedType->getCoroutineKind(),
ParameterConvention::Direct_Unowned,
- interfaceParams, interfaceResults,
- interfaceErrorResult,
+ interfaceParams, interfaceYields,
+ interfaceResults, interfaceErrorResult,
getASTContext());
}
diff --git a/lib/SILOptimizer/ARC/ARCRegionState.cpp b/lib/SILOptimizer/ARC/ARCRegionState.cpp
index e4c2eed..f776571 100644
--- a/lib/SILOptimizer/ARC/ARCRegionState.cpp
+++ b/lib/SILOptimizer/ARC/ARCRegionState.cpp
@@ -170,6 +170,8 @@
// against the operand or can use the value in some way.
case TermKind::ThrowInst:
case TermKind::ReturnInst:
+ case TermKind::UnwindInst:
+ case TermKind::YieldInst:
case TermKind::TryApplyInst:
case TermKind::SwitchValueInst:
case TermKind::SwitchEnumInst:
diff --git a/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp b/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp
index bf3d1ae..50ae744 100644
--- a/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp
+++ b/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp
@@ -211,6 +211,8 @@
// against the operand or can use the value in some way.
case TermKind::ThrowInst:
case TermKind::ReturnInst:
+ case TermKind::UnwindInst:
+ case TermKind::YieldInst:
case TermKind::TryApplyInst:
case TermKind::SwitchValueInst:
case TermKind::SwitchEnumInst:
diff --git a/lib/SILOptimizer/Analysis/CFG.cpp b/lib/SILOptimizer/Analysis/CFG.cpp
index ef1b825..e0e84de 100644
--- a/lib/SILOptimizer/Analysis/CFG.cpp
+++ b/lib/SILOptimizer/Analysis/CFG.cpp
@@ -34,6 +34,11 @@
case TermKind::UnreachableInst:
case TermKind::ReturnInst:
case TermKind::ThrowInst:
+ case TermKind::UnwindInst:
+ return false;
+ // yield and try_apply are special because they can do arbitrary,
+ // potentially-process-terminating things.
+ case TermKind::YieldInst:
case TermKind::TryApplyInst:
return false;
}
diff --git a/lib/SILOptimizer/IPO/CapturePromotion.cpp b/lib/SILOptimizer/IPO/CapturePromotion.cpp
index 49b1c64..ddaacb2 100644
--- a/lib/SILOptimizer/IPO/CapturePromotion.cpp
+++ b/lib/SILOptimizer/IPO/CapturePromotion.cpp
@@ -416,7 +416,8 @@
// Create the thin function type for the cloned closure.
auto ClonedTy = SILFunctionType::get(
OrigFTI->getGenericSignature(), OrigFTI->getExtInfo(),
- OrigFTI->getCalleeConvention(), ClonedInterfaceArgTys,
+ OrigFTI->getCoroutineKind(), OrigFTI->getCalleeConvention(),
+ ClonedInterfaceArgTys, OrigFTI->getYields(),
OrigFTI->getResults(), OrigFTI->getOptionalErrorResult(),
M.getASTContext(), OrigFTI->getWitnessMethodConformanceOrNone());
diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
index 73c0ff0..c21f9c9 100644
--- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
+++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
@@ -614,8 +614,9 @@
auto ClonedTy = SILFunctionType::get(
ClosureUserFunTy->getGenericSignature(), ExtInfo,
+ ClosureUserFunTy->getCoroutineKind(),
ClosureUserFunTy->getCalleeConvention(), NewParameterInfoList,
- ClosureUserFunTy->getResults(),
+ ClosureUserFunTy->getYields(), ClosureUserFunTy->getResults(),
ClosureUserFunTy->getOptionalErrorResult(), M.getASTContext());
// We make this function bare so we don't have to worry about decls in the
diff --git a/lib/SILOptimizer/IPO/GlobalOpt.cpp b/lib/SILOptimizer/IPO/GlobalOpt.cpp
index 7de21a7..4d3581c 100644
--- a/lib/SILOptimizer/IPO/GlobalOpt.cpp
+++ b/lib/SILOptimizer/IPO/GlobalOpt.cpp
@@ -260,7 +260,8 @@
SILFunctionType::ExtInfo EInfo;
EInfo = EInfo.withRepresentation(SILFunctionType::Representation::Thin);
auto LoweredType = SILFunctionType::get(nullptr, EInfo,
- ParameterConvention::Direct_Owned, { }, Results, None,
+ SILCoroutineKind::None, ParameterConvention::Direct_Owned,
+ /*params*/ {}, /*yields*/ {}, Results, None,
Store->getModule().getASTContext());
auto *GetterF = Store->getModule().getOrCreateFunction(
Store->getLoc(),
@@ -514,7 +515,8 @@
SILFunctionType::ExtInfo EInfo;
EInfo = EInfo.withRepresentation(SILFunctionType::Representation::Thin);
auto LoweredType = SILFunctionType::get(nullptr, EInfo,
- ParameterConvention::Direct_Owned, { }, Results, None,
+ SILCoroutineKind::None, ParameterConvention::Direct_Owned,
+ /*params*/ {}, /*yields*/ {}, Results, None,
InitF->getASTContext());
auto *GetterF = InitF->getModule().getOrCreateFunction(
InitF->getLocation(),
diff --git a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
index b92c698..996215f 100644
--- a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
+++ b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
@@ -629,7 +629,8 @@
// the parameters promoted.
auto ClonedTy = SILFunctionType::get(
OrigFTI->getGenericSignature(), OrigFTI->getExtInfo(),
- OrigFTI->getCalleeConvention(), ClonedInterfaceArgTys,
+ OrigFTI->getCoroutineKind(), OrigFTI->getCalleeConvention(),
+ ClonedInterfaceArgTys, OrigFTI->getYields(),
OrigFTI->getResults(), OrigFTI->getOptionalErrorResult(),
M.getASTContext(), OrigFTI->getWitnessMethodConformanceOrNone());
diff --git a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
index 6d0e0df..5e1bca0 100644
--- a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
+++ b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
@@ -291,6 +291,8 @@
switch (Term->getTermKind()) {
case TermKind::ReturnInst:
case TermKind::ThrowInst:
+ case TermKind::UnwindInst:
+ case TermKind::YieldInst:
case TermKind::UnreachableInst:
case TermKind::SwitchValueInst:
@@ -381,6 +383,7 @@
switch (cast<TermInst>(I)->getTermKind()) {
case TermKind::BranchInst:
case TermKind::UnreachableInst:
+ case TermKind::UnwindInst:
return;
case TermKind::ReturnInst:
@@ -396,6 +399,7 @@
case TermKind::TryApplyInst:
case TermKind::SwitchValueInst:
+ case TermKind::YieldInst:
for (auto &O : I->getAllOperands())
markValueLive(O.get());
return;
diff --git a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
index c3304da..f43224d 100644
--- a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
+++ b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
@@ -577,6 +577,12 @@
InterfaceResults.push_back(InterfaceResult);
}
+ llvm::SmallVector<SILYieldInfo, 8> InterfaceYields;
+ for (SILYieldInfo InterfaceYield : FTy->getYields()) {
+ // For now, don't touch the yield types.
+ InterfaceYields.push_back(InterfaceYield);
+ }
+
bool UsesGenerics = false;
if (HasGenericSignature) {
// Not all of the generic type parameters are used by the function
@@ -630,9 +636,9 @@
UsesGenerics ? FTy->getGenericSignature() : nullptr;
return SILFunctionType::get(
- GenericSig, ExtInfo, FTy->getCalleeConvention(), InterfaceParams,
- InterfaceResults, InterfaceErrorResult, F->getModule().getASTContext(),
- witnessMethodConformance);
+ GenericSig, ExtInfo, FTy->getCoroutineKind(), FTy->getCalleeConvention(),
+ InterfaceParams, InterfaceYields, InterfaceResults, InterfaceErrorResult,
+ F->getModule().getASTContext(), witnessMethodConformance);
}
void FunctionSignatureTransform::createFunctionSignatureOptimizedFunction() {
diff --git a/lib/SILOptimizer/Transforms/Outliner.cpp b/lib/SILOptimizer/Transforms/Outliner.cpp
index 76741f7..47cc57e 100644
--- a/lib/SILOptimizer/Transforms/Outliner.cpp
+++ b/lib/SILOptimizer/Transforms/Outliner.cpp
@@ -290,7 +290,8 @@
SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
/*pseudogeneric*/ false, /*noescape*/ false);
auto FunctionType = SILFunctionType::get(
- nullptr, ExtInfo, ParameterConvention::Direct_Unowned, Parameters,
+ nullptr, ExtInfo, SILCoroutineKind::None,
+ ParameterConvention::Direct_Unowned, Parameters, /*yields*/ {},
Results, None, M.getASTContext());
return FunctionType;
}
@@ -1197,7 +1198,8 @@
SILResultInfo(BridgedReturn.getReturnType(), ResultConvention::Owned));
}
auto FunctionType = SILFunctionType::get(
- nullptr, ExtInfo, ParameterConvention::Direct_Unowned, Parameters,
+ nullptr, ExtInfo, SILCoroutineKind::None,
+ ParameterConvention::Direct_Unowned, Parameters, {},
Results, None, M.getASTContext());
return FunctionType;
}
diff --git a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
index fe6da5e..145a57b 100644
--- a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
+++ b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
@@ -2302,6 +2302,8 @@
case TermKind::ThrowInst:
case TermKind::DynamicMethodBranchInst:
case TermKind::ReturnInst:
+ case TermKind::UnwindInst:
+ case TermKind::YieldInst:
break;
}
// If the block has a cond_fail, try to move it to the predecessors.
diff --git a/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp b/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp
index 3d6da3c..4219ac2 100644
--- a/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp
+++ b/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp
@@ -84,7 +84,8 @@
nullptr, SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
false /*isPseudoGeneric*/,
false /*noescape*/),
- ParameterConvention::Direct_Unowned, ArrayRef<SILParameterInfo>(),
+ SILCoroutineKind::None, ParameterConvention::Direct_Unowned,
+ ArrayRef<SILParameterInfo>(), ArrayRef<SILYieldInfo>(),
ResultInfoArray, None, getFunction()->getModule().getASTContext());
SILFunction *F = getFunction()->getModule().getOrCreateSharedFunction(
diff --git a/lib/SILOptimizer/Utils/CFG.cpp b/lib/SILOptimizer/Utils/CFG.cpp
index 452e58d..9f419ba 100644
--- a/lib/SILOptimizer/Utils/CFG.cpp
+++ b/lib/SILOptimizer/Utils/CFG.cpp
@@ -307,9 +307,25 @@
return;
}
+ case TermKind::YieldInst: {
+ auto *YI = cast<YieldInst>(T);
+ assert((EdgeIdx == 0 || EdgeIdx == 1) && "Invalid edge index");
+ auto *resumeBB = !EdgeIdx ? NewDest : YI->getResumeBB();
+ auto *unwindBB = EdgeIdx ? NewDest : YI->getUnwindBB();
+ SmallVector<SILValue, 4> yieldedValues;
+ for (auto value : YI->getYieldedValues())
+ yieldedValues.push_back(value);
+
+ B.createYield(YI->getLoc(), yieldedValues, resumeBB, unwindBB);
+
+ YI->eraseFromParent();
+ return;
+ }
+
case TermKind::ReturnInst:
case TermKind::ThrowInst:
case TermKind::UnreachableInst:
+ case TermKind::UnwindInst:
llvm_unreachable("Branch target cannot be changed for this terminator instruction!");
}
llvm_unreachable("Not yet implemented!");
@@ -469,6 +485,8 @@
case TermKind::ThrowInst:
case TermKind::TryApplyInst:
case TermKind::UnreachableInst:
+ case TermKind::UnwindInst:
+ case TermKind::YieldInst:
llvm_unreachable("Branch target cannot be replaced for this terminator instruction!");
}
llvm_unreachable("Not yet implemented!");
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index e7dfb6f..eb69a59 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -721,8 +721,10 @@
// Use the new specialized generic signature.
auto NewFnTy = SILFunctionType::get(
- CanSpecializedGenericSig, FnTy->getExtInfo(), FnTy->getCalleeConvention(),
- FnTy->getParameters(), FnTy->getResults(), FnTy->getOptionalErrorResult(),
+ CanSpecializedGenericSig, FnTy->getExtInfo(),
+ FnTy->getCoroutineKind(), FnTy->getCalleeConvention(),
+ FnTy->getParameters(), FnTy->getYields(),
+ FnTy->getResults(), FnTy->getOptionalErrorResult(),
M.getASTContext(), FnTy->getWitnessMethodConformanceOrNone());
// This is an interface type. It should not have any archetypes.
@@ -735,6 +737,7 @@
CanSILFunctionType ReabstractionInfo::
createSpecializedType(CanSILFunctionType SubstFTy, SILModule &M) const {
llvm::SmallVector<SILResultInfo, 8> SpecializedResults;
+ llvm::SmallVector<SILYieldInfo, 8> SpecializedYields;
llvm::SmallVector<SILParameterInfo, 8> SpecializedParams;
unsigned IndirectResultIdx = 0;
@@ -769,9 +772,15 @@
SpecializedParams.push_back(PI);
}
}
+ for (SILYieldInfo YI : SubstFTy->getYields()) {
+ // For now, always just use the original, substituted parameter info.
+ SpecializedYields.push_back(YI);
+ }
return SILFunctionType::get(
- SubstFTy->getGenericSignature(), SubstFTy->getExtInfo(),
- SubstFTy->getCalleeConvention(), SpecializedParams, SpecializedResults,
+ SubstFTy->getGenericSignature(),
+ SubstFTy->getExtInfo(), SubstFTy->getCoroutineKind(),
+ SubstFTy->getCalleeConvention(),
+ SpecializedParams, SpecializedYields, SpecializedResults,
SubstFTy->getOptionalErrorResult(), M.getASTContext(),
SubstFTy->getWitnessMethodConformanceOrNone());
}
diff --git a/lib/SILOptimizer/Utils/SILInliner.cpp b/lib/SILOptimizer/Utils/SILInliner.cpp
index 96c67bb..1fdf29d 100644
--- a/lib/SILOptimizer/Utils/SILInliner.cpp
+++ b/lib/SILOptimizer/Utils/SILInliner.cpp
@@ -338,6 +338,8 @@
case SILInstructionKind::UnreachableInst:
case SILInstructionKind::ReturnInst:
case SILInstructionKind::ThrowInst:
+ case SILInstructionKind::UnwindInst:
+ case SILInstructionKind::YieldInst:
return InlineCost::Free;
case SILInstructionKind::ApplyInst:
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index ca96300..2c4fded 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -7527,6 +7527,16 @@
DC);
if (!useAs && !useAsBang)
return false;
+
+ // If we're performing pattern matching, "as" means something completely different...
+ if (auto binOpExpr = dyn_cast<BinaryExpr>(expr)) {
+ auto overloadedFn = dyn_cast<OverloadedDeclRefExpr>(binOpExpr->getFn());
+ if (overloadedFn && overloadedFn->getDecls().size() > 0) {
+ ValueDecl *decl0 = overloadedFn->getDecls()[0];
+ if (decl0->getBaseName() == decl0->getASTContext().Id_MatchOperator)
+ return false;
+ }
+ }
bool needsParensInside = exprNeedsParensBeforeAddingAs(TC, DC, affected);
bool needsParensOutside = exprNeedsParensAfterAddingAs(TC, DC, affected,
diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp
index 9a42ad4..3025c13 100644
--- a/lib/Sema/TypeCheckAvailability.cpp
+++ b/lib/Sema/TypeCheckAvailability.cpp
@@ -1499,6 +1499,27 @@
IsUnavailable);
}
+bool TypeChecker::isInsideCompatibleUnavailableDeclaration(
+ SourceRange ReferenceRange, const DeclContext *ReferenceDC,
+ const AvailableAttr *attr) {
+ if (!attr->isUnconditionallyUnavailable()) {
+ return false;
+ }
+ PlatformKind platform = attr->Platform;
+ if (platform == PlatformKind::none) {
+ return false;
+ }
+
+ auto IsUnavailable = [platform](const Decl *D) {
+ auto EnclosingUnavailable =
+ D->getAttrs().getUnavailable(D->getASTContext());
+ return EnclosingUnavailable && EnclosingUnavailable->Platform == platform;
+ };
+
+ return someEnclosingDeclMatches(ReferenceRange, ReferenceDC, *this,
+ IsUnavailable);
+}
+
bool TypeChecker::isInsideDeprecatedDeclaration(SourceRange ReferenceRange,
const DeclContext *ReferenceDC){
auto IsDeprecated = [](const Decl *D) {
@@ -2093,6 +2114,14 @@
return false;
}
+ // Calling unavailable code from within code with the same
+ // unavailability is OK -- the eventual caller can't call the
+ // enclosing code in the same situations it wouldn't be able to
+ // call this code.
+ if (isInsideCompatibleUnavailableDeclaration(R, DC, Attr)) {
+ return false;
+ }
+
SourceLoc Loc = R.Start;
auto Name = D->getFullName();
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index f53508b..0cdbf53 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -2348,25 +2348,14 @@
// Replace generic type parameters and associated types with their
// witnesses, when we have them.
auto selfTy = conformance->getProtocol()->getSelfInterfaceType();
- type = type.transform([&](Type type) -> Type {
- // If a dependent member refers to an associated type, replace it.
- if (auto member = type->getAs<DependentMemberType>()) {
- if (member->getBase()->isEqual(selfTy)) {
- // FIXME: Could handle inherited conformances here.
- if (conformance->hasTypeWitness(member->getAssocType()))
- return conformance->getTypeWitness(member->getAssocType(), nullptr);
- }
- }
+ return type.subst([&](SubstitutableType *dependentType) {
+ if (dependentType->isEqual(selfTy))
+ return conformance->getType();
- // Replace 'Self' with the conforming type.
- if (type->isEqual(selfTy))
- return conformance->getType();
-
- return type;
- });
-
- //
- return type;
+ return Type(dependentType);
+ },
+ LookUpConformanceInModule(module),
+ SubstFlags::UseErrorType);
}
/// \brief Retrieve the kind of requirement described by the given declaration,
@@ -6356,6 +6345,24 @@
return false;
}
+/// Determine whether this is an unlabeled initializer or subscript.
+static bool isUnlabeledInitializerOrSubscript(ValueDecl *value) {
+ ParameterList *paramList = nullptr;
+ if (auto constructor = dyn_cast<ConstructorDecl>(value))
+ paramList = constructor->getParameterList(1);
+ else if (auto subscript = dyn_cast<SubscriptDecl>(value))
+ paramList = subscript->getIndices();
+ else
+ return false;
+
+ for (auto param : *paramList) {
+ if (!param->getArgumentName().empty()) return false;
+ }
+
+ return true;
+}
+
+/// Determine whether this declaration is an initializer
/// Determine whether we should warn about the given witness being a close
/// match for the given optional requirement.
static bool shouldWarnAboutPotentialWitness(
@@ -6390,6 +6397,12 @@
if (!attr->isImplicit()) return false;
}
+ // Don't warn if the requirement or witness is an initializer or subscript
+ // with no argument labels.
+ if (isUnlabeledInitializerOrSubscript(req) ||
+ isUnlabeledInitializerOrSubscript(witness))
+ return false;
+
// If the score is relatively high, don't warn: this is probably
// unrelated. Allow about one typo for every four properly-typed
// characters, which prevents completely-wacky suggestions in many
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 9cd8bd7..9aa42f8 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -1702,17 +1702,25 @@
TypeResolutionOptions options,
FunctionType::ExtInfo extInfo
= FunctionType::ExtInfo());
- Type resolveSILFunctionType(
- FunctionTypeRepr *repr, TypeResolutionOptions options,
- SILFunctionType::ExtInfo extInfo = SILFunctionType::ExtInfo(),
- ParameterConvention calleeConvention = DefaultParameterConvention,
- TypeRepr *witnessmethodProtocol = nullptr);
+ Type resolveSILFunctionType(FunctionTypeRepr *repr,
+ TypeResolutionOptions options,
+ SILCoroutineKind coroutineKind
+ = SILCoroutineKind::None,
+ SILFunctionType::ExtInfo extInfo
+ = SILFunctionType::ExtInfo(),
+ ParameterConvention calleeConvention
+ = DefaultParameterConvention,
+ TypeRepr *witnessmethodProtocol = nullptr);
SILParameterInfo resolveSILParameter(TypeRepr *repr,
TypeResolutionOptions options);
+ SILYieldInfo resolveSILYield(TypeAttributes &remainingAttrs,
+ TypeRepr *repr, TypeResolutionOptions options);
bool resolveSILResults(TypeRepr *repr, TypeResolutionOptions options,
+ SmallVectorImpl<SILYieldInfo> &yields,
SmallVectorImpl<SILResultInfo> &results,
Optional<SILResultInfo> &errorResult);
bool resolveSingleSILResult(TypeRepr *repr, TypeResolutionOptions options,
+ SmallVectorImpl<SILYieldInfo> &yields,
SmallVectorImpl<SILResultInfo> &results,
Optional<SILResultInfo> &errorResult);
Type resolveSpecifierTypeRepr(SpecifierTypeRepr *repr,
@@ -1970,7 +1978,7 @@
static const TypeAttrKind FunctionAttrs[] = {
TAK_convention, TAK_noreturn, TAK_pseudogeneric,
TAK_callee_owned, TAK_callee_guaranteed, TAK_noescape, TAK_autoclosure,
- TAK_escaping
+ TAK_escaping, TAK_yield_once, TAK_yield_many
};
auto checkUnsupportedAttr = [&](TypeAttrKind attr) {
@@ -2018,6 +2026,13 @@
SILFunctionType::Representation rep;
TypeRepr *witnessMethodProtocol = nullptr;
+ auto coroutineKind = SILCoroutineKind::None;
+ if (attrs.has(TAK_yield_once)) {
+ coroutineKind = SILCoroutineKind::YieldOnce;
+ } else if (attrs.has(TAK_yield_many)) {
+ coroutineKind = SILCoroutineKind::YieldMany;
+ }
+
auto calleeConvention = ParameterConvention::Direct_Unowned;
if (attrs.has(TAK_callee_owned)) {
if (attrs.has(TAK_callee_guaranteed)) {
@@ -2065,7 +2080,8 @@
SILFunctionType::ExtInfo extInfo(rep, attrs.has(TAK_pseudogeneric),
attrs.has(TAK_noescape));
- ty = resolveSILFunctionType(fnRepr, options, extInfo, calleeConvention,
+ ty = resolveSILFunctionType(fnRepr, options, coroutineKind,
+ extInfo, calleeConvention,
witnessMethodProtocol);
if (!ty || ty->hasError()) return ty;
} else if (hasFunctionAttr) {
@@ -2257,6 +2273,11 @@
options -= TR_ImmediateFunctionInput;
options -= TR_FunctionInput;
options -= TR_TypeAliasUnderlyingType;
+ // FIXME: Until we remove the IUO type from the type system, we
+ // need to continue to parse IUOs in SIL tests so that we can
+ // match the types we generate from the importer.
+ if (!options.contains(TR_SILMode))
+ options -= TR_AllowIUO;
Type inputTy = resolveType(repr->getArgsTypeRepr(),
options | TR_ImmediateFunctionInput);
@@ -2424,6 +2445,7 @@
Type TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr,
TypeResolutionOptions options,
+ SILCoroutineKind coroutineKind,
SILFunctionType::ExtInfo extInfo,
ParameterConvention callee,
TypeRepr *witnessMethodProtocol) {
@@ -2436,6 +2458,7 @@
// Resolve parameter and result types using the function's generic
// environment.
SmallVector<SILParameterInfo, 4> params;
+ SmallVector<SILYieldInfo, 4> yields;
SmallVector<SILResultInfo, 4> results;
Optional<SILResultInfo> errorResult;
{
@@ -2484,10 +2507,17 @@
{
// FIXME: Deal with unsatisfied dependencies.
- if (resolveSILResults(repr->getResultTypeRepr(), options,
+ if (resolveSILResults(repr->getResultTypeRepr(), options, yields,
results, errorResult)) {
hasError = true;
}
+
+ // Diagnose non-coroutines that declare yields.
+ if (coroutineKind == SILCoroutineKind::None && !yields.empty()) {
+ TC.diagnose(repr->getResultTypeRepr()->getLoc(),
+ diag::sil_non_coro_yields);
+ hasError = true;
+ }
}
} // restore generic type resolver
@@ -2498,6 +2528,7 @@
// FIXME: Remap the parsed context types to interface types.
CanGenericSignature genericSig;
SmallVector<SILParameterInfo, 4> interfaceParams;
+ SmallVector<SILYieldInfo, 4> interfaceYields;
SmallVector<SILResultInfo, 4> interfaceResults;
Optional<SILResultInfo> interfaceErrorResult;
if (auto *genericEnv = repr->getGenericEnvironment()) {
@@ -2508,6 +2539,11 @@
param.getType())->getCanonicalType();
interfaceParams.push_back(param.getWithType(transParamType));
}
+ for (auto &yield : yields) {
+ auto transYieldType = genericEnv->mapTypeOutOfContext(
+ yield.getType())->getCanonicalType();
+ interfaceYields.push_back(yield.getWithType(transYieldType));
+ }
for (auto &result : results) {
auto transResultType = genericEnv->mapTypeOutOfContext(
result.getType())->getCanonicalType();
@@ -2522,6 +2558,7 @@
}
} else {
interfaceParams = params;
+ interfaceYields = yields;
interfaceResults = results;
interfaceErrorResult = errorResult;
}
@@ -2552,9 +2589,20 @@
"found witness_method without matching conformance");
}
- return SILFunctionType::get(genericSig, extInfo, callee, interfaceParams,
- interfaceResults, interfaceErrorResult, Context,
- witnessMethodConformance);
+ return SILFunctionType::get(genericSig, extInfo, coroutineKind,
+ callee,
+ interfaceParams, interfaceYields,
+ interfaceResults, interfaceErrorResult,
+ Context, witnessMethodConformance);
+}
+
+SILYieldInfo TypeResolver::resolveSILYield(TypeAttributes &attrs,
+ TypeRepr *repr,
+ TypeResolutionOptions options) {
+ AttributedTypeRepr attrRepr(attrs, repr);
+ SILParameterInfo paramInfo =
+ resolveSILParameter(&attrRepr, options | TR_ImmediateFunctionInput);
+ return SILYieldInfo(paramInfo.getType(), paramInfo.getConvention());
}
SILParameterInfo TypeResolver::resolveSILParameter(
@@ -2568,6 +2616,7 @@
if (auto attrRepr = dyn_cast<AttributedTypeRepr>(repr)) {
auto attrs = attrRepr->getAttrs();
+
auto checkFor = [&](TypeAttrKind tak, ParameterConvention attrConv) {
if (!attrs.has(tak)) return;
if (convention != DefaultParameterConvention) {
@@ -2610,6 +2659,7 @@
bool TypeResolver::resolveSingleSILResult(TypeRepr *repr,
TypeResolutionOptions options,
+ SmallVectorImpl<SILYieldInfo> &yields,
SmallVectorImpl<SILResultInfo> &ordinaryResults,
Optional<SILResultInfo> &errorResult) {
Type type;
@@ -2620,6 +2670,19 @@
// Copy the attributes out; we're going to destructively modify them.
auto attrs = attrRepr->getAttrs();
+ // Recognize @yields.
+ if (attrs.has(TypeAttrKind::TAK_yields)) {
+ attrs.clearAttribute(TypeAttrKind::TAK_yields);
+
+ // The treatment from this point on is basically completely different.
+ auto yield = resolveSILYield(attrs, attrRepr->getTypeRepr(), options);
+ if (yield.getType()->hasError())
+ return true;
+
+ yields.push_back(yield);
+ return false;
+ }
+
// Recognize @error.
if (attrs.has(TypeAttrKind::TAK_error)) {
attrs.clearAttribute(TypeAttrKind::TAK_error);
@@ -2687,6 +2750,7 @@
bool TypeResolver::resolveSILResults(TypeRepr *repr,
TypeResolutionOptions options,
+ SmallVectorImpl<SILYieldInfo> &yields,
SmallVectorImpl<SILResultInfo> &ordinaryResults,
Optional<SILResultInfo> &errorResult) {
if (auto tuple = dyn_cast<TupleTypeRepr>(repr)) {
@@ -2696,13 +2760,15 @@
TC.diagnose(element.UnderscoreLoc, diag::sil_function_output_label);
}
for (auto elt : tuple->getElements()) {
- if (resolveSingleSILResult(elt.Type, options, ordinaryResults, errorResult))
+ if (resolveSingleSILResult(elt.Type, options,
+ yields, ordinaryResults, errorResult))
hadError = true;
}
return hadError;
}
- return resolveSingleSILResult(repr, options, ordinaryResults, errorResult);
+ return resolveSingleSILResult(repr, options,
+ yields, ordinaryResults, errorResult);
}
Type TypeResolver::resolveSpecifierTypeRepr(SpecifierTypeRepr *repr,
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index bf862ae..db21218 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -2376,6 +2376,12 @@
bool isInsideUnavailableDeclaration(SourceRange ReferenceRange,
const DeclContext *DC);
+ /// Returns true if the reference or any of its parents is an
+ /// unconditional unavailable declaration for the same platform.
+ bool isInsideCompatibleUnavailableDeclaration(SourceRange ReferenceRange,
+ const DeclContext *DC,
+ const AvailableAttr *attr);
+
/// Returns true if the reference is lexically contained in a declaration
/// that is deprecated on all deployment targets.
bool isInsideDeprecatedDeclaration(SourceRange ReferenceRange,
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 68890a2..b62babb 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -439,9 +439,11 @@
unsigned kind = Cursor.readRecord(next.ID, scratch);
switch (kind) {
case decls_block::SIL_LAYOUT: {
+ GenericSignatureID rawGenericSig;
unsigned numFields;
ArrayRef<uint64_t> types;
- decls_block::SILLayoutLayout::readRecord(scratch, numFields, types);
+ decls_block::SILLayoutLayout::readRecord(scratch, rawGenericSig,
+ numFields, types);
SmallVector<SILField, 4> fields;
for (auto fieldInfo : types.slice(0, numFields)) {
@@ -452,20 +454,10 @@
isMutable));
}
- SmallVector<GenericTypeParamType*, 4> genericParams;
- for (auto typeId : types.slice(numFields)) {
- auto type = getType(typeId)->castTo<GenericTypeParamType>();
- genericParams.push_back(type);
- }
-
- SmallVector<Requirement, 4> requirements;
- readGenericRequirements(requirements, DeclTypeCursor);
- CanGenericSignature sig;
- if (!genericParams.empty() || !requirements.empty()) {
- sig = GenericSignature::get(genericParams, requirements)
- ->getCanonicalSignature();
- }
- return SILLayout::get(getContext(), sig, fields);
+ CanGenericSignature canSig;
+ if (auto sig = getGenericSignature(rawGenericSig))
+ canSig = sig->getCanonicalSignature();
+ return SILLayout::get(getContext(), canSig, fields);
}
default:
error();
@@ -920,6 +912,68 @@
}
}
+GenericSignature *ModuleFile::getGenericSignature(
+ serialization::GenericSignatureID ID) {
+ using namespace decls_block;
+
+ // Zero is a sentinel for having no generic signature.
+ if (ID == 0) return nullptr;
+
+ assert(ID <= GenericSignatures.size() && "invalid GenericSignature ID");
+ auto &sigOrOffset = GenericSignatures[ID-1];
+
+ // If we've already deserialized this generic signature, return it.
+ if (sigOrOffset.isComplete()) {
+ return sigOrOffset.get();
+ }
+
+ // Read the generic signature.
+ BCOffsetRAII restoreOffset(DeclTypeCursor);
+ DeclTypeCursor.JumpToBit(sigOrOffset);
+ DeserializingEntityRAII deserializingEntity(*this);
+
+ // Read the parameter types.
+ SmallVector<GenericTypeParamType *, 4> paramTypes;
+ StringRef blobData;
+ SmallVector<uint64_t, 8> scratch;
+
+ auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
+ if (entry.Kind != llvm::BitstreamEntry::Record) {
+ error();
+ return nullptr;
+ }
+
+ unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData);
+ if (recordID != GENERIC_SIGNATURE) {
+ error();
+ return nullptr;
+ }
+
+ ArrayRef<uint64_t> rawParamIDs;
+ GenericSignatureLayout::readRecord(scratch, rawParamIDs);
+
+ for (unsigned i = 0, n = rawParamIDs.size(); i != n; ++i) {
+ auto paramTy = getType(rawParamIDs[i])->castTo<GenericTypeParamType>();
+ paramTypes.push_back(paramTy);
+ }
+
+ // Read the generic requirements.
+ SmallVector<Requirement, 4> requirements;
+ readGenericRequirements(requirements, DeclTypeCursor);
+
+ // Construct the generic signature from the loaded parameters and
+ // requirements.
+ auto signature = GenericSignature::get(paramTypes, requirements);
+
+ // If we've already deserialized this generic signature, return it.
+ if (sigOrOffset.isComplete()) {
+ return sigOrOffset.get();
+ }
+
+ sigOrOffset = signature;
+ return signature;
+}
+
llvm::PointerUnion<GenericSignature *, GenericEnvironment *>
ModuleFile::getGenericSignatureOrEnvironment(
serialization::GenericEnvironmentID ID,
@@ -940,13 +994,21 @@
return envOrOffset.get();
}
- // Read the generic environment.
- BCOffsetRAII restoreOffset(DeclTypeCursor);
- DeclTypeCursor.JumpToBit(envOrOffset);
- DeserializingEntityRAII deserializingEntity(*this);
+ // Extract the bit offset or generic signature ID.
+ uint64_t bitOffset = envOrOffset;
+ GenericSignature *signature = nullptr;
+ if (bitOffset & 0x01) {
+ // We have a generic signature ID.
+ signature = getGenericSignature(bitOffset >> 1);
+ } else {
+ bitOffset = bitOffset >> 1;
- SmallVector<GenericTypeParamType *, 4> paramTypes;
- {
+ // Read the generic environment.
+ BCOffsetRAII restoreOffset(DeclTypeCursor);
+ DeclTypeCursor.JumpToBit(bitOffset);
+ DeserializingEntityRAII deserializingEntity(*this);
+
+ SmallVector<GenericTypeParamType *, 4> paramTypes;
using namespace decls_block;
StringRef blobData;
@@ -963,72 +1025,55 @@
return result;
unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData);
- switch (recordID) {
- case GENERIC_ENVIRONMENT: {
- lastRecordOffset.reset();
-
- ArrayRef<uint64_t> rawParamIDs;
- GenericEnvironmentLayout::readRecord(scratch, rawParamIDs);
-
- for (unsigned i = 0, n = rawParamIDs.size(); i != n; ++i) {
- auto paramTy = getType(rawParamIDs[i])->castTo<GenericTypeParamType>();
- paramTypes.push_back(paramTy);
- }
- break;
- }
-
- case SIL_GENERIC_ENVIRONMENT: {
- ArrayRef<uint64_t> rawParamIDs;
- SILGenericEnvironmentLayout::readRecord(scratch, rawParamIDs);
- lastRecordOffset.reset();
-
- if (rawParamIDs.size() % 2 != 0) {
- error();
- return result;
- }
-
- for (unsigned i = 0, n = rawParamIDs.size(); i != n; i += 2) {
- Identifier name = getIdentifier(rawParamIDs[i]);
- auto paramTy = getType(rawParamIDs[i+1])->castTo<GenericTypeParamType>();
-
- if (!name.empty()) {
- auto paramDecl =
- createDecl<GenericTypeParamDecl>(getAssociatedModule(),
- name,
- SourceLoc(),
- paramTy->getDepth(),
- paramTy->getIndex());
- paramTy = paramDecl->getDeclaredInterfaceType()
- ->castTo<GenericTypeParamType>();
- }
-
- paramTypes.push_back(paramTy);
- }
- break;
- }
-
- default:
+ if (recordID != SIL_GENERIC_ENVIRONMENT) {
error();
return result;
}
+
+ ArrayRef<uint64_t> rawParamIDs;
+ SILGenericEnvironmentLayout::readRecord(scratch, rawParamIDs);
+ lastRecordOffset.reset();
+
+ if (rawParamIDs.size() % 2 != 0) {
+ error();
+ return result;
+ }
+
+ for (unsigned i = 0, n = rawParamIDs.size(); i != n; i += 2) {
+ Identifier name = getIdentifier(rawParamIDs[i]);
+ auto paramTy = getType(rawParamIDs[i+1])->castTo<GenericTypeParamType>();
+
+ if (!name.empty()) {
+ auto paramDecl =
+ createDecl<GenericTypeParamDecl>(getAssociatedModule(),
+ name,
+ SourceLoc(),
+ paramTy->getDepth(),
+ paramTy->getIndex());
+ paramTy = paramDecl->getDeclaredInterfaceType()
+ ->castTo<GenericTypeParamType>();
+ }
+
+ paramTypes.push_back(paramTy);
+ }
+
+ // If there are no parameters, the environment is empty.
+ if (paramTypes.empty()) {
+ if (wantEnvironment)
+ envOrOffset = nullptr;
+
+ return result;
+ }
+
+ // Read the generic requirements.
+ SmallVector<Requirement, 4> requirements;
+ readGenericRequirements(requirements, DeclTypeCursor);
+
+ // Construct the generic signature from the loaded parameters and
+ // requirements.
+ signature = GenericSignature::get(paramTypes, requirements);
}
- // If there are no parameters, the environment is empty.
- if (paramTypes.empty()) {
- if (wantEnvironment)
- envOrOffset = nullptr;
-
- return result;
- }
-
- // Read the generic requirements.
- SmallVector<Requirement, 4> requirements;
- readGenericRequirements(requirements, DeclTypeCursor);
-
- // Construct the generic signature from the loaded parameters and
- // requirements.
- auto signature = GenericSignature::get(paramTypes, requirements);
-
// If we only want the signature, return it now.
if (!wantEnvironment) return signature;
@@ -1465,23 +1510,13 @@
case XREF_EXTENSION_PATH_PIECE: {
ModuleID ownerID;
- ArrayRef<uint64_t> genericParamIDs;
- XRefExtensionPathPieceLayout::readRecord(scratch, ownerID,
- genericParamIDs);
+ GenericSignatureID rawGenericSig;
+ XRefExtensionPathPieceLayout::readRecord(scratch, ownerID, rawGenericSig);
M = getModule(ownerID);
pathTrace.addExtension(M);
// Read the generic signature, if we have one.
- if (!genericParamIDs.empty()) {
- SmallVector<GenericTypeParamType *, 4> params;
- SmallVector<Requirement, 5> requirements;
- for (TypeID paramID : genericParamIDs) {
- params.push_back(getType(paramID)->castTo<GenericTypeParamType>());
- }
- readGenericRequirements(requirements, DeclTypeCursor);
-
- genericSig = GenericSignature::getCanonical(params, requirements);
- }
+ genericSig = CanGenericSignature(getGenericSignature(rawGenericSig));
continue;
}
@@ -3771,6 +3806,26 @@
}
}
+/// Translate from the Serialization coroutine kind enum values to the AST
+/// strongly-typed enum.
+///
+/// The former is guaranteed to be stable, but may not reflect this version of
+/// the AST.
+static Optional<swift::SILCoroutineKind>
+getActualSILCoroutineKind(uint8_t rep) {
+ switch (rep) {
+#define CASE(KIND) \
+ case (uint8_t)serialization::SILCoroutineKind::KIND: \
+ return swift::SILCoroutineKind::KIND;
+ CASE(None)
+ CASE(YieldOnce)
+ CASE(YieldMany)
+#undef CASE
+ default:
+ return None;
+ }
+}
+
/// Translate from the serialization Ownership enumerators, which are
/// guaranteed to be stable, to the AST ones.
static
@@ -4248,40 +4303,23 @@
TypeID resultID;
uint8_t rawRep;
bool throws = false;
- ArrayRef<uint64_t> genericParamIDs;
+ GenericSignatureID rawGenericSig;
decls_block::GenericFunctionTypeLayout::readRecord(scratch,
inputID,
resultID,
rawRep,
throws,
- genericParamIDs);
+ rawGenericSig);
auto rep = getActualFunctionTypeRepresentation(rawRep);
if (!rep.hasValue()) {
error();
return nullptr;
}
- // Read the generic parameters.
- SmallVector<GenericTypeParamType *, 4> genericParams;
- for (auto paramID : genericParamIDs) {
- auto param = dyn_cast_or_null<GenericTypeParamType>(
- getType(paramID).getPointer());
- if (!param) {
- error();
- break;
- }
-
- genericParams.push_back(param);
- }
-
- // Read the generic requirements.
- SmallVector<Requirement, 4> requirements;
- readGenericRequirements(requirements, DeclTypeCursor);
+ auto sig = getGenericSignature(rawGenericSig);
auto info = GenericFunctionType::ExtInfo(*rep, throws);
-
- auto sig = GenericSignature::get(genericParams, requirements);
-
+
auto inputTy = getTypeChecked(inputID);
if (!inputTy)
return inputTy.takeError();
@@ -4354,23 +4392,29 @@
}
case decls_block::SIL_FUNCTION_TYPE: {
+ uint8_t rawCoroutineKind;
uint8_t rawCalleeConvention;
uint8_t rawRepresentation;
bool pseudogeneric = false;
bool noescape;
bool hasErrorResult;
unsigned numParams;
+ unsigned numYields;
unsigned numResults;
+ GenericSignatureID rawGenericSig;
ArrayRef<uint64_t> variableData;
decls_block::SILFunctionTypeLayout::readRecord(scratch,
+ rawCoroutineKind,
rawCalleeConvention,
rawRepresentation,
pseudogeneric,
noescape,
hasErrorResult,
numParams,
+ numYields,
numResults,
+ rawGenericSig,
variableData);
// Process the ExtInfo.
@@ -4382,6 +4426,13 @@
}
SILFunctionType::ExtInfo extInfo(*representation, pseudogeneric, noescape);
+ // Process the coroutine kind.
+ auto coroutineKind = getActualSILCoroutineKind(rawCoroutineKind);
+ if (!coroutineKind.hasValue()) {
+ error();
+ return nullptr;
+ }
+
// Process the callee convention.
auto calleeConvention = getActualParameterConvention(rawCalleeConvention);
if (!calleeConvention.hasValue()) {
@@ -4397,6 +4448,14 @@
return SILParameterInfo(type->getCanonicalType(), *convention);
};
+ auto processYield = [&](TypeID typeID, uint64_t rawConvention)
+ -> Optional<SILYieldInfo> {
+ auto convention = getActualParameterConvention(rawConvention);
+ auto type = getType(typeID);
+ if (!convention || !type) return None;
+ return SILYieldInfo(type->getCanonicalType(), *convention);
+ };
+
auto processResult = [&](TypeID typeID, uint64_t rawConvention)
-> Optional<SILResultInfo> {
auto convention = getActualResultConvention(rawConvention);
@@ -4428,6 +4487,20 @@
allParams.push_back(*param);
}
+ // Process the yields.
+ SmallVector<SILYieldInfo, 8> allYields;
+ allYields.reserve(numYields);
+ for (unsigned i = 0; i != numYields; ++i) {
+ auto typeID = variableData[nextVariableDataIndex++];
+ auto rawConvention = variableData[nextVariableDataIndex++];
+ auto yield = processYield(typeID, rawConvention);
+ if (!yield) {
+ error();
+ return nullptr;
+ }
+ allYields.push_back(*yield);
+ }
+
// Process the results.
SmallVector<SILResultInfo, 8> allResults;
allParams.reserve(numResults);
@@ -4454,30 +4527,19 @@
}
}
- // Process the generic signature parameters.
- SmallVector<GenericTypeParamType *, 8> genericParamTypes;
- for (auto id : variableData.slice(nextVariableDataIndex)) {
- genericParamTypes.push_back(
- cast<GenericTypeParamType>(getType(id)->getCanonicalType()));
- }
-
Optional<ProtocolConformanceRef> witnessMethodConformance;
if (*representation == SILFunctionTypeRepresentation::WitnessMethod) {
witnessMethodConformance = readConformance(DeclTypeCursor);
}
- // Read the generic requirements, if any.
- SmallVector<Requirement, 4> requirements;
- readGenericRequirements(requirements, DeclTypeCursor);
+ GenericSignature *genericSig = getGenericSignature(rawGenericSig);
- GenericSignature *genericSig = nullptr;
- if (!genericParamTypes.empty() || !requirements.empty())
- genericSig = GenericSignature::get(genericParamTypes, requirements,
- /*isKnownCanonical=*/true);
-
- typeOrOffset = SILFunctionType::get(
- genericSig, extInfo, calleeConvention.getValue(), allParams, allResults,
- errorResult, ctx, witnessMethodConformance);
+ typeOrOffset = SILFunctionType::get(genericSig, extInfo,
+ coroutineKind.getValue(),
+ calleeConvention.getValue(),
+ allParams, allYields, allResults,
+ errorResult,
+ ctx, witnessMethodConformance);
break;
}
@@ -4891,21 +4953,7 @@
// Requirement -> synthetic map.
SmallVector<Substitution, 4> reqToSyntheticSubs;
- if (unsigned numGenericParams = *rawIDIter++) {
- // Generic parameters of the synthetic environment.
- SmallVector<GenericTypeParamType *, 2> genericParams;
- while (numGenericParams--) {
- genericParams.push_back(
- getType(*rawIDIter++)->castTo<GenericTypeParamType>());
- }
-
- // Generic requirements of the synthetic environment.
- SmallVector<Requirement, 4> requirements;
- readGenericRequirements(requirements, DeclTypeCursor);
-
- // Form the generic signature for the synthetic environment.
- syntheticSig = GenericSignature::get(genericParams, requirements);
-
+ if (auto syntheticSig = getGenericSignature(*rawIDIter++)) {
// Create the synthetic environment.
syntheticEnv = syntheticSig->createGenericEnvironment();
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index fcdcb48..b1e78e8 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -710,7 +710,7 @@
(SILDeclRef::Kind)ListOfValues[NextIdx+1],
(swift::ResilienceExpansion)ListOfValues[NextIdx+2],
/*isCurried=*/false, ListOfValues[NextIdx+4] > 0);
- if (ListOfValues[NextIdx+3] < DRef.getUncurryLevel())
+ if (ListOfValues[NextIdx+3] < DRef.getParameterListCount() - 1)
DRef = DRef.asCurried();
NextIdx += 5;
return DRef;
@@ -2112,6 +2112,27 @@
ResultVal = Builder.createUnreachable(Loc);
break;
}
+ case SILInstructionKind::UnwindInst: {
+ ResultVal = Builder.createUnwind(Loc);
+ break;
+ }
+ case SILInstructionKind::YieldInst: {
+ SILBasicBlock *unwindBB = getBBForReference(Fn, ListOfValues.back());
+ ListOfValues = ListOfValues.drop_back();
+ SILBasicBlock *resumeBB = getBBForReference(Fn, ListOfValues.back());
+ ListOfValues = ListOfValues.drop_back();
+
+ SmallVector<SILValue, 4> yieldedValues;
+ for (unsigned I = 0, E = ListOfValues.size(); I < E; I += 3) {
+ auto valueTy = MF->getType(ListOfValues[I]);
+ auto valueCategory = (SILValueCategory) ListOfValues[I+1];
+ yieldedValues.push_back(
+ getLocalValue(ListOfValues[I+2], getSILType(valueTy, valueCategory)));
+ }
+
+ ResultVal = Builder.createYield(Loc, yieldedValues, resumeBB, unwindBB);
+ break;
+ }
case SILInstructionKind::KeyPathInst: {
unsigned nextValue = 0;
SILType kpTy
diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp
index 94c42c2..a9b83c7 100644
--- a/lib/Serialization/ModuleFile.cpp
+++ b/lib/Serialization/ModuleFile.cpp
@@ -16,6 +16,7 @@
#include "swift/Subsystems.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTMangler.h"
+#include "swift/AST/GenericSignature.h"
#include "swift/AST/ModuleLoader.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/USRGeneration.h"
@@ -842,6 +843,10 @@
assert(blobData.empty());
LocalDeclContexts.assign(scratch.begin(), scratch.end());
break;
+ case index_block::GENERIC_SIGNATURE_OFFSETS:
+ assert(blobData.empty());
+ GenericSignatures.assign(scratch.begin(), scratch.end());
+ break;
case index_block::GENERIC_ENVIRONMENT_OFFSETS:
assert(blobData.empty());
GenericEnvironments.assign(scratch.begin(), scratch.end());
@@ -2170,6 +2175,17 @@
return File.Bits.HasEntryPoint;
}
+bool SerializedASTFile::getAllGenericSignatures(
+ SmallVectorImpl<GenericSignature*> &genericSignatures) {
+ genericSignatures.clear();
+ for (unsigned index : indices(File.GenericSignatures)) {
+ if (auto genericSig = File.getGenericSignature(index + 1))
+ genericSignatures.push_back(genericSig);
+ }
+
+ return true;
+}
+
ClassDecl *SerializedASTFile::getMainClass() const {
assert(hasEntryPoint());
return cast_or_null<ClassDecl>(File.getDecl(File.Bits.EntryPointDeclID));
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 524bc75..9b0ec56 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -531,6 +531,19 @@
return id;
}
+GenericSignatureID Serializer::addGenericSignatureRef(
+ const GenericSignature *env) {
+ if (!env) return 0;
+
+ auto &id = GenericSignatureIDs[env];
+ if (id != 0)
+ return id;
+
+ id = ++LastGenericSignatureID;
+ GenericSignaturesToWrite.push(env);
+ return id;
+}
+
GenericEnvironmentID Serializer::addGenericEnvironmentRef(
const GenericEnvironment *env) {
if (!env) return 0;
@@ -759,10 +772,10 @@
BLOCK_RECORD(index_block, OBJC_METHODS);
BLOCK_RECORD(index_block, ENTRY_POINT);
BLOCK_RECORD(index_block, LOCAL_DECL_CONTEXT_OFFSETS);
+ BLOCK_RECORD(index_block, GENERIC_SIGNATURE_OFFSETS);
BLOCK_RECORD(index_block, GENERIC_ENVIRONMENT_OFFSETS);
BLOCK_RECORD(index_block, DECL_CONTEXT_OFFSETS);
BLOCK_RECORD(index_block, LOCAL_TYPE_DECLS);
- BLOCK_RECORD(index_block, GENERIC_ENVIRONMENT_OFFSETS);
BLOCK_RECORD(index_block, NORMAL_CONFORMANCE_OFFSETS);
BLOCK_RECORD(index_block, SIL_LAYOUT_OFFSETS);
BLOCK_RECORD(index_block, PRECEDENCE_GROUPS);
@@ -1349,6 +1362,31 @@
return true;
}
+void Serializer::writeGenericSignature(const GenericSignature *sig) {
+ using namespace decls_block;
+
+ // Record the offset of this generic environment.
+ auto id = GenericSignatureIDs[sig];
+ assert(id != 0 && "generic signature not referenced properly");
+ (void)id;
+
+ assert((id - 1) == GenericSignatureOffsets.size());
+ GenericSignatureOffsets.push_back(Out.GetCurrentBitNo());
+
+ assert(sig != nullptr);
+
+ // Record the generic parameters.
+ SmallVector<uint64_t, 4> rawParamIDs;
+ for (auto *paramTy : sig->getGenericParams()) {
+ rawParamIDs.push_back(addTypeRef(paramTy));
+ }
+
+ auto abbrCode = DeclTypeAbbrCodes[GenericSignatureLayout::Code];
+ GenericSignatureLayout::emitRecord(Out, ScratchRecord, abbrCode, rawParamIDs);
+
+ writeGenericRequirements(sig->getRequirements(), DeclTypeAbbrCodes);
+}
+
void Serializer::writeGenericEnvironment(const GenericEnvironment *env) {
using namespace decls_block;
@@ -1358,10 +1396,7 @@
(void)id;
assert((id - 1) == GenericEnvironmentOffsets.size());
- GenericEnvironmentOffsets.push_back(Out.GetCurrentBitNo());
-
- if (env == nullptr)
- return;
+ assert(env != nullptr);
// Determine whether we must use SIL mode, because one of the generic
// parameters has a declaration with module context.
@@ -1375,33 +1410,36 @@
}
}
+ // If not in SIL mode, generic environments just contain a reference to
+ // the generic signature.
+ if (!SILMode) {
+ // Record the generic signature directly.
+ auto genericSigID = addGenericSignatureRef(env->getGenericSignature());
+ GenericEnvironmentOffsets.push_back((genericSigID << 1) | 0x01);
+ return;
+ }
+
+ // Record the current bit.
+ GenericEnvironmentOffsets.push_back((Out.GetCurrentBitNo() << 1));
+
// Record the generic parameters.
SmallVector<uint64_t, 4> rawParamIDs;
for (auto *paramTy : env->getGenericParams()) {
auto *decl = paramTy->getDecl();
// In SIL mode, add the name and canonicalize the parameter type.
- if (SILMode) {
- if (decl)
- rawParamIDs.push_back(addDeclBaseNameRef(decl->getName()));
- else
- rawParamIDs.push_back(addDeclBaseNameRef(Identifier()));
+ if (decl)
+ rawParamIDs.push_back(addDeclBaseNameRef(decl->getName()));
+ else
+ rawParamIDs.push_back(addDeclBaseNameRef(Identifier()));
- paramTy = paramTy->getCanonicalType()->castTo<GenericTypeParamType>();
- }
-
+ paramTy = paramTy->getCanonicalType()->castTo<GenericTypeParamType>();
rawParamIDs.push_back(addTypeRef(paramTy));
}
- if (SILMode) {
- auto envAbbrCode = DeclTypeAbbrCodes[SILGenericEnvironmentLayout::Code];
- SILGenericEnvironmentLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
- rawParamIDs);
- } else {
- auto envAbbrCode = DeclTypeAbbrCodes[GenericEnvironmentLayout::Code];
- GenericEnvironmentLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
- rawParamIDs);
- }
+ auto envAbbrCode = DeclTypeAbbrCodes[SILGenericEnvironmentLayout::Code];
+ SILGenericEnvironmentLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
+ rawParamIDs);
writeGenericRequirements(env->getGenericSignature()->getRequirements(),
DeclTypeAbbrCodes);
@@ -1425,22 +1463,14 @@
data.push_back(typeRef);
}
- // Save generic params.
- if (auto sig = layout->getGenericSignature()) {
- for (auto param : sig->getGenericParams()) {
- data.push_back(addTypeRef(param));
- }
- }
-
unsigned abbrCode
= DeclTypeAbbrCodes[SILLayoutLayout::Code];
- SILLayoutLayout::emitRecord(Out, ScratchRecord, abbrCode,
- layout->getFields().size(),
- data);
- // Emit requirements.
- if (auto sig = layout->getGenericSignature())
- writeGenericRequirements(sig->getRequirements(), DeclTypeAbbrCodes);
+ SILLayoutLayout::emitRecord(
+ Out, ScratchRecord, abbrCode,
+ addGenericSignatureRef(layout->getGenericSignature()),
+ layout->getFields().size(),
+ data);
}
void Serializer::writeNormalConformance(
@@ -1477,19 +1507,14 @@
if (auto genericEnv = witness.requiresSubstitution()
? witness.getSyntheticEnvironment()
: nullptr) {
+ // Generic signature.
auto *genericSig = genericEnv->getGenericSignature();
-
- // Generic parameters.
- data.push_back(genericSig->getGenericParams().size());
- for (auto gp : genericSig->getGenericParams())
- data.push_back(addTypeRef(gp));
+ data.push_back(addGenericSignatureRef(genericSig));
auto reqToSyntheticSubs = witness.getRequirementToSyntheticSubs();
data.push_back(reqToSyntheticSubs.size());
-
- // Requirements come at the end.
} else {
- data.push_back(/*number of generic parameters*/0);
+ data.push_back(/*null generic signature*/0);
}
data.push_back(witness.getSubstitutions().size());
@@ -1531,12 +1556,6 @@
if (auto genericEnv = witness.requiresSubstitution()
? witness.getSyntheticEnvironment()
: nullptr) {
- auto *genericSig = genericEnv->getGenericSignature();
-
- // Write the generic requirements of the synthetic environment.
- writeGenericRequirements(genericSig->getRequirements(),
- DeclTypeAbbrCodes);
-
// Write requirement-to-synthetic substitutions.
writeSubstitutions(witness.getRequirementToSyntheticSubs(),
DeclTypeAbbrCodes,
@@ -1866,21 +1885,13 @@
writeCrossReference(baseTy->getAnyNominal(), pathLen + 1);
abbrCode = DeclTypeAbbrCodes[XRefExtensionPathPieceLayout::Code];
- SmallVector<TypeID, 4> genericParams;
CanGenericSignature genericSig(nullptr);
if (ext->isConstrainedExtension()) {
genericSig = ext->getGenericSignature()->getCanonicalSignature();
- for (auto param : genericSig->getGenericParams())
- genericParams.push_back(addTypeRef(param));
}
XRefExtensionPathPieceLayout::emitRecord(
Out, ScratchRecord, abbrCode, addModuleRef(DC->getParentModule()),
- genericParams);
-
- if (genericSig) {
- writeGenericRequirements(genericSig->getRequirements(),
- DeclTypeAbbrCodes);
- }
+ addGenericSignatureRef(genericSig));
break;
}
@@ -3354,6 +3365,18 @@
llvm_unreachable("bad calling convention");
}
+/// Translate from the AST coroutine-kind enum to the Serialization enum
+/// values, which are guaranteed to be stable.
+static uint8_t getRawStableSILCoroutineKind(
+ swift::SILCoroutineKind kind) {
+ switch (kind) {
+ SIMPLE_CASE(SILCoroutineKind, None)
+ SIMPLE_CASE(SILCoroutineKind, YieldOnce)
+ SIMPLE_CASE(SILCoroutineKind, YieldMany)
+ }
+ llvm_unreachable("bad kind");
+}
+
/// Translate from the AST ownership enum to the Serialization enum
/// values, which are guaranteed to be stable.
static uint8_t getRawStableOwnership(swift::Ownership ownership) {
@@ -3616,19 +3639,12 @@
case TypeKind::GenericFunction: {
auto fnTy = cast<GenericFunctionType>(ty.getPointer());
unsigned abbrCode = DeclTypeAbbrCodes[GenericFunctionTypeLayout::Code];
- SmallVector<TypeID, 4> genericParams;
- for (auto param : fnTy->getGenericParams())
- genericParams.push_back(addTypeRef(param));
GenericFunctionTypeLayout::emitRecord(Out, ScratchRecord, abbrCode,
addTypeRef(fnTy->getInput()),
addTypeRef(fnTy->getResult()),
getRawStableFunctionTypeRepresentation(fnTy->getRepresentation()),
fnTy->throws(),
- genericParams);
-
- // Write requirements.
- writeGenericRequirements(fnTy->getRequirements(),
- DeclTypeAbbrCodes);
+ addGenericSignatureRef(fnTy->getGenericSignature()));
break;
}
@@ -3674,6 +3690,11 @@
unsigned conv = getRawStableParameterConvention(param.getConvention());
variableData.push_back(TypeID(conv));
}
+ for (auto yield : fnTy->getYields()) {
+ variableData.push_back(addTypeRef(yield.getType()));
+ unsigned conv = getRawStableParameterConvention(yield.getConvention());
+ variableData.push_back(TypeID(conv));
+ }
for (auto result : fnTy->getResults()) {
variableData.push_back(addTypeRef(result.getType()));
unsigned conv = getRawStableResultConvention(result.getConvention());
@@ -3687,27 +3708,25 @@
}
auto sig = fnTy->getGenericSignature();
- if (sig) {
- for (auto param : sig->getGenericParams())
- variableData.push_back(addTypeRef(param));
- }
+
+ auto stableCoroutineKind =
+ getRawStableSILCoroutineKind(fnTy->getCoroutineKind());
auto stableCalleeConvention =
getRawStableParameterConvention(fnTy->getCalleeConvention());
unsigned abbrCode = DeclTypeAbbrCodes[SILFunctionTypeLayout::Code];
SILFunctionTypeLayout::emitRecord(
- Out, ScratchRecord, abbrCode, stableCalleeConvention,
+ Out, ScratchRecord, abbrCode,
+ stableCoroutineKind, stableCalleeConvention,
stableRepresentation, fnTy->isPseudogeneric(), fnTy->isNoEscape(),
fnTy->hasErrorResult(), fnTy->getParameters().size(),
- fnTy->getNumResults(), variableData);
+ fnTy->getNumYields(), fnTy->getNumResults(),
+ addGenericSignatureRef(sig), variableData);
if (auto conformance = fnTy->getWitnessMethodConformanceOrNone())
writeConformance(*conformance, DeclTypeAbbrCodes);
- if (sig)
- writeGenericRequirements(sig->getRequirements(),
- DeclTypeAbbrCodes);
break;
}
@@ -3891,7 +3910,7 @@
registerDeclTypeAbbr<GenericParamLayout>();
registerDeclTypeAbbr<GenericRequirementLayout>();
registerDeclTypeAbbr<LayoutRequirementLayout>();
- registerDeclTypeAbbr<GenericEnvironmentLayout>();
+ registerDeclTypeAbbr<GenericSignatureLayout>();
registerDeclTypeAbbr<SILGenericEnvironmentLayout>();
registerDeclTypeAbbr<ForeignErrorConventionLayout>();
@@ -3951,6 +3970,12 @@
writeDeclContext(next);
}
+ while (!GenericSignaturesToWrite.empty()) {
+ auto next = GenericSignaturesToWrite.front();
+ GenericSignaturesToWrite.pop();
+ writeGenericSignature(next);
+ }
+
while (!GenericEnvironmentsToWrite.empty()) {
auto next = GenericEnvironmentsToWrite.front();
GenericEnvironmentsToWrite.pop();
@@ -3972,6 +3997,7 @@
!LocalDeclContextsToWrite.empty() ||
!DeclContextsToWrite.empty() ||
!SILLayoutsToWrite.empty() ||
+ !GenericSignaturesToWrite.empty() ||
!GenericEnvironmentsToWrite.empty() ||
!NormalConformancesToWrite.empty());
}
@@ -4769,6 +4795,7 @@
writeOffsets(Offsets, IdentifierOffsets);
writeOffsets(Offsets, DeclContextOffsets);
writeOffsets(Offsets, LocalDeclContextOffsets);
+ writeOffsets(Offsets, GenericSignatureOffsets);
writeOffsets(Offsets, GenericEnvironmentOffsets);
writeOffsets(Offsets, NormalConformanceOffsets);
writeOffsets(Offsets, SILLayoutOffsets);
diff --git a/lib/Serialization/Serialization.h b/lib/Serialization/Serialization.h
index 59a3eba..340f88a 100644
--- a/lib/Serialization/Serialization.h
+++ b/lib/Serialization/Serialization.h
@@ -100,6 +100,10 @@
/// A map from local DeclContexts to their serialized IDs.
llvm::DenseMap<const DeclContext*, DeclContextID> LocalDeclContextIDs;
+ /// A map from generic signatures to their serialized IDs.
+ llvm::DenseMap<const GenericSignature *, GenericSignatureID>
+ GenericSignatureIDs;
+
/// A map from generic environments to their serialized IDs.
llvm::DenseMap<const GenericEnvironment *, GenericEnvironmentID>
GenericEnvironmentIDs;
@@ -167,6 +171,9 @@
/// Local DeclContexts that need to be serialized.
std::queue<const DeclContext*> LocalDeclContextsToWrite;
+ /// Generic signatures that need to be serialized.
+ std::queue<const GenericSignature *> GenericSignaturesToWrite;
+
/// Generic environments that need to be serialized.
std::queue<const GenericEnvironment*> GenericEnvironmentsToWrite;
@@ -202,6 +209,10 @@
/// IdentifierID.
std::vector<CharOffset> IdentifierOffsets;
+ /// The offset of each GenericSignature in the bitstream, indexed by
+ /// GenericSignatureID.
+ std::vector<BitOffset> GenericSignatureOffsets;
+
/// The offset of each GenericEnvironment in the bitstream, indexed by
/// GenericEnvironmentID.
std::vector<BitOffset> GenericEnvironmentOffsets;
@@ -242,6 +253,10 @@
uint32_t /*IdentifierID*/ LastIdentifierID =
serialization::NUM_SPECIAL_IDS - 1;
+ /// The last assigned GenericSignatureID for generic signature from this
+ /// module.
+ uint32_t /*GenericSignatureID*/ LastGenericSignatureID = 0;
+
/// The last assigned GenericEnvironmentID for generic environments from this
/// module.
uint32_t /*GenericEnvironmentID*/ LastGenericEnvironmentID = 0;
@@ -261,6 +276,8 @@
return index_block::DECL_CONTEXT_OFFSETS;
if (&values == &LocalDeclContextOffsets)
return index_block::LOCAL_DECL_CONTEXT_OFFSETS;
+ if (&values == &GenericSignatureOffsets)
+ return index_block::GENERIC_SIGNATURE_OFFSETS;
if (&values == &GenericEnvironmentOffsets)
return index_block::GENERIC_ENVIRONMENT_OFFSETS;
if (&values == &NormalConformanceOffsets)
@@ -354,6 +371,9 @@
/// Writes the given type.
void writeType(Type ty);
+ /// Writes a generic signature.
+ void writeGenericSignature(const GenericSignature *sig);
+
/// Writes a generic environment.
void writeGenericEnvironment(const GenericEnvironment *env);
@@ -436,6 +456,11 @@
/// The DeclContext will be scheduled for serialization if necessary.
DeclContextID addLocalDeclContextRef(const DeclContext *DC);
+ /// Records the use of the given generic signature.
+ ///
+ /// The GenericSignature will be scheduled for serialization if necessary.
+ GenericSignatureID addGenericSignatureRef(const GenericSignature *sig);
+
/// Records the use of the given generic environment.
///
/// The GenericEnvironment will be scheduled for serialization if necessary.
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index 237f38f..02317e9 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -482,7 +482,7 @@
ListOfValues.push_back(S.addDeclRef(Ref.getDecl()));
ListOfValues.push_back((unsigned)Ref.kind);
ListOfValues.push_back((unsigned)Ref.getResilienceExpansion());
- ListOfValues.push_back(Ref.getUncurryLevel());
+ ListOfValues.push_back(Ref.getParameterListCount() - 1);
ListOfValues.push_back(Ref.isForeign);
}
@@ -582,6 +582,7 @@
// TODO: decide if we want to serialize those instructions.
return;
+ case SILInstructionKind::UnwindInst:
case SILInstructionKind::UnreachableInst: {
unsigned abbrCode = SILAbbrCodes[SILInstNoOperandLayout::Code];
SILInstNoOperandLayout::emitRecord(Out, ScratchRecord, abbrCode,
@@ -1124,6 +1125,21 @@
writeOneOperandLayout(SI.getKind(), Attr, SI.getOperand(0));
break;
}
+ case SILInstructionKind::YieldInst: {
+ auto YI = cast<YieldInst>(&SI);
+ SmallVector<ValueID, 4> args;
+ for (auto arg: YI->getYieldedValues()) {
+ args.push_back(S.addTypeRef(arg->getType().getSwiftRValueType()));
+ args.push_back((unsigned)arg->getType().getCategory());
+ args.push_back(addValueRef(arg));
+ }
+ args.push_back(BasicBlockMap[YI->getResumeBB()]);
+ args.push_back(BasicBlockMap[YI->getUnwindBB()]);
+ SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
+ SILAbbrCodes[SILOneTypeValuesLayout::Code],
+ (unsigned)YI->getKind(), 0, 0, args);
+ break;
+ }
case SILInstructionKind::FunctionRefInst: {
// Use SILOneOperandLayout to specify the function type and the function
// name (IdentifierID).
diff --git a/lib/Syntax/SyntaxFactory.cpp.gyb b/lib/Syntax/SyntaxFactory.cpp.gyb
index b534351..f57d2361 100644
--- a/lib/Syntax/SyntaxFactory.cpp.gyb
+++ b/lib/Syntax/SyntaxFactory.cpp.gyb
@@ -57,6 +57,18 @@
return make<UnknownSyntax>(Raw);
}
+Syntax SyntaxFactory::makeBlankCollectionSyntax(SyntaxKind Kind) {
+ switch(Kind) {
+% for node in SYNTAX_NODES:
+% if node.is_syntax_collection():
+ case SyntaxKind::${node.syntax_kind}: return makeBlank${node.syntax_kind}();
+% end
+% end
+ default: break;
+ }
+ llvm_unreachable("not collection kind.");
+}
+
Optional<Syntax>
SyntaxFactory::createSyntax(SyntaxKind Kind, llvm::ArrayRef<Syntax> Elements) {
switch(Kind) {
diff --git a/lib/Syntax/SyntaxParsingContext.cpp b/lib/Syntax/SyntaxParsingContext.cpp
index eb8e495..04b50d9 100644
--- a/lib/Syntax/SyntaxParsingContext.cpp
+++ b/lib/Syntax/SyntaxParsingContext.cpp
@@ -56,19 +56,34 @@
assert(StartLoc.isValid() == EndLoc.isValid());
return SourceRange(StartLoc, EndLoc);
}
+
+static RawSyntaxInfo createSyntaxAs(ArrayRef<RawSyntaxInfo> Parts,
+ SyntaxKind Kind) {
+ llvm::SmallVector<Syntax, 8> Scratch;
+ auto SyntaxParts = getSyntaxNodes(Parts, Scratch);
+
+ // Try to create the node of the given syntax.
+ Optional<Syntax> Result = SyntaxFactory::createSyntax(Kind, SyntaxParts);
+ if (!Result) {
+
+ // If unable to create, we should create an unknown node.
+ Result.emplace(makeUnknownSyntax(SyntaxFactory::getUnknownKind(Kind),
+ SyntaxParts));
+ }
+ return { getNodesRange(Parts), Result->getRaw() };
+}
} // End of anonymous namespace
struct SyntaxParsingContext::ContextInfo {
bool Enabled;
private:
SourceLoc ContextStartLoc;
- SourceLoc ContextEndLoc;
std::vector<RawSyntaxInfo> PendingSyntax;
// All tokens after the start of this context.
ArrayRef<RawSyntaxInfo> Tokens;
- ArrayRef<RawSyntaxInfo>::const_iterator findTokenAt(SourceLoc Loc) {
+ ArrayRef<RawSyntaxInfo>::const_iterator findTokenAt(SourceLoc Loc) const {
for (auto It = Tokens.begin(); It != Tokens.end(); It ++) {
assert(It->getStartLoc() == It->getEndLoc());
if (It->getStartLoc() == Loc)
@@ -96,10 +111,13 @@
}
// Squash N syntax nodex from the back of the pending list into one.
- void createFromBack(SyntaxKind Kind, unsigned N = 0);
- std::vector<RawSyntaxInfo> collectAllSyntax();
+ void createFromBackTokens(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> UsedTokens,
+ unsigned N);
+ void createWhole(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> NodesToUse);
+ std::vector<RawSyntaxInfo> collectAllSyntax(SourceLoc EndLoc);
ArrayRef<RawSyntaxInfo> allTokens() const { return Tokens; }
- ArrayRef<RawSyntaxInfo> getPendingSyntax() const { return PendingSyntax; };
+ ArrayRef<RawSyntaxInfo> getPendingSyntax() const { return PendingSyntax; }
+ SourceLoc getContextStartLoc() const { return ContextStartLoc; }
void addPendingSyntax(RawSyntaxInfo Info) {
assert(Info.isImplicit() || PendingSyntax.empty() ||
@@ -114,42 +132,65 @@
Tokens = Tokens.slice(findTokenAt(Loc) - Tokens.begin());
}
- void setContextEnd(SourceLoc Loc) {
- assert(ContextEndLoc.isInvalid());
- ContextEndLoc = Loc;
- Tokens = Tokens.take_front(findTokenAt(Loc) - Tokens.begin());
- }
-
- void promoteTokenAt(SourceLoc Loc) {
- PendingSyntax.push_back(*findTokenAt(Loc));
+ ArrayRef<RawSyntaxInfo> dropTokenAt(SourceLoc Loc) const {
+ return Tokens.take_front(findTokenAt(Loc) - Tokens.begin());
}
// Check if the pending syntax is a token syntax in the given kind.
- bool checkTokenFromBack(tok Kind, unsigned OffsetFromBack = 0) {
- if (PendingSyntax.size() - 1 < OffsetFromBack)
+ bool checkTokenFromBack(tok Kind, ArrayRef<RawSyntaxInfo> UsedTokens,
+ unsigned OffsetFromBack = 0) {
+ if (UsedTokens.size() - 1 < OffsetFromBack)
return false;
- auto Back = PendingSyntax[PendingSyntax.size() - 1 - OffsetFromBack].
+ auto Back = UsedTokens[UsedTokens.size() - 1 - OffsetFromBack].
makeSyntax<Syntax>().getAs<TokenSyntax>();
return Back.hasValue() && Back->getTokenKind() == Kind;
}
};
+static void addNodeToResults(std::vector<RawSyntaxInfo> &Results,
+ std::vector<RawSyntaxInfo> &ImplicitNodes,
+ RawSyntaxInfo Info) {
+ // Add implicit nodes before adding the explicit nodes they attach to.
+ assert(!Info.isImplicit());
+ auto StartSize = Results.size();
+
+ // Find all implicit nodes where the attach-to location is the start position
+ // of this non-implicit nodes.
+ Results.insert(Results.end(),
+ std::find_if(ImplicitNodes.begin(), ImplicitNodes.end(),
+ [&](const RawSyntaxInfo &Imp) {
+ return Imp.BeforeLoc == Info.getStartLoc();
+ }),
+ ImplicitNodes.end());
+
+ // If any implicit nodes are inserted to results, we should clear the buffer
+ // to avoid re-inserting them.
+ if (StartSize != Results.size()) {
+ ImplicitNodes.clear();
+ }
+
+ // Add the non-implicit node.
+ Results.emplace_back(Info);
+}
+
std::vector<RawSyntaxInfo>
-SyntaxParsingContext::ContextInfo::collectAllSyntax() {
+SyntaxParsingContext::ContextInfo::collectAllSyntax(SourceLoc EndLoc) {
std::vector<RawSyntaxInfo> Results;
+ std::vector<RawSyntaxInfo> ImplicitNodes;
auto CurSyntax = PendingSyntax.begin();
- for (auto It = Tokens.begin(); It != Tokens.end();) {
+ for (auto It = Tokens.begin(); It->getStartLoc() != EndLoc;) {
auto Tok = *It;
if (CurSyntax == PendingSyntax.end()) {
// If no remaining syntax nodes, add the token.
- Results.emplace_back(Tok);
+ addNodeToResults(Results, ImplicitNodes, Tok);
It ++;
} else if (CurSyntax->isImplicit()) {
+ ImplicitNodes.emplace_back(*CurSyntax);
// Skip implicit syntax node.
CurSyntax ++;
} else if (CurSyntax->getStartLoc() == Tok.getStartLoc()) {
// Prefer syntax nodes to tokens.
- Results.emplace_back(*CurSyntax);
+ addNodeToResults(Results, ImplicitNodes, *CurSyntax);
while(It->getEndLoc() != CurSyntax->getEndLoc()) It++;
assert(It < Tokens.end() && It->getEndLoc() == CurSyntax->getEndLoc());
It ++;
@@ -159,7 +200,7 @@
// started.
assert(Tok.getStartLoc().getOpaquePointerValue() <
CurSyntax->getStartLoc().getOpaquePointerValue());
- Results.push_back(Tok);
+ addNodeToResults(Results, ImplicitNodes, Tok);
It ++;
}
}
@@ -170,40 +211,30 @@
return Results;
}
-void
-SyntaxParsingContext::ContextInfo::createFromBack(SyntaxKind Kind, unsigned N) {
- auto Size = PendingSyntax.size();
- if (!N)
- N = Size;
- assert(Size >= N);
- auto Parts = llvm::makeArrayRef(PendingSyntax).slice(Size - N);
- llvm::SmallVector<Syntax, 8> Scratch;
- auto SyntaxParts = getSyntaxNodes(Parts, Scratch);
+void SyntaxParsingContext::ContextInfo::
+createFromBackTokens(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> UsedTokens,
+ unsigned N) {
+ auto Size = UsedTokens.size();
+ assert(N && Size >= N);
+ auto Parts = llvm::makeArrayRef(UsedTokens).slice(Size - N);
+ addPendingSyntax(createSyntaxAs(Parts, Kind));
+}
- // Try to create the node of the given syntax.
- Optional<Syntax> Result = SyntaxFactory::createSyntax(Kind, SyntaxParts);
- if (!Result) {
-
- // If unable to create, we should create an unknown node.
- Result.emplace(makeUnknownSyntax(SyntaxFactory::getUnknownKind(Kind),
- SyntaxParts));
- }
- RawSyntaxInfo NewSyntaxNode(getNodesRange(Parts), Result->getRaw());
-
- // Remove the building bricks and re-append the result.
- for (unsigned I = 0; I < N; I ++)
- PendingSyntax.pop_back();
- addPendingSyntax(NewSyntaxNode);
- assert(Size - N + 1 == PendingSyntax.size());
+void SyntaxParsingContext::ContextInfo::
+createWhole(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> NodesToUse) {
+ auto Result = createSyntaxAs(NodesToUse, Kind);
+ PendingSyntax.clear();
+ addPendingSyntax(Result);
}
SyntaxParsingContext::
SyntaxParsingContext(SourceFile &SF, unsigned BufferID, Token &Tok):
- ContextData(*new ContextInfo(SF, BufferID)), Tok(Tok) {}
+ ContextData(*new ContextInfo(SF, BufferID)),
+ Tok(Tok) {}
SyntaxParsingContext::SyntaxParsingContext(SyntaxParsingContext &Another):
ContextData(*new ContextInfo(Another.ContextData.allTokens(),
- Another.ContextData.Enabled)), Tok(Another.Tok) {}
+ Another.ContextData.Enabled)), Tok(Another.Tok) {}
SyntaxParsingContext::~SyntaxParsingContext() { delete &ContextData; }
@@ -250,15 +281,11 @@
ContextData.setContextStart(Tok.getLoc());
}
-
-void SyntaxParsingContextChild::addTokenSyntax(SourceLoc Loc) {
- if (ContextData.Enabled)
- ContextData.promoteTokenAt(Loc);
-}
-
-void SyntaxParsingContextChild::makeNode(SyntaxKind Kind) {
+void SyntaxParsingContextChild::makeNode(SyntaxKind Kind, SourceLoc LastTokLoc) {
if (!ContextData.Enabled)
return;
+ auto UsedTokens = ContextData.dropTokenAt(LastTokLoc);
+ UsedTokens = llvm::makeArrayRef(UsedTokens.data(), UsedTokens.size() + 1);
// Create syntax nodes according to the given kind.
switch (Kind) {
@@ -266,12 +293,12 @@
case SyntaxKind::IntegerLiteralExpr: {
// Integer may include the signs before the digits, so check if the sign
// exists and create.
- ContextData.createFromBack(Kind, ContextData.
- checkTokenFromBack(tok::oper_prefix, 1) ? 2 : 1);
+ ContextData.createFromBackTokens(Kind, UsedTokens, ContextData.
+ checkTokenFromBack(tok::oper_prefix, UsedTokens, 1) ? 2 : 1);
break;
}
case SyntaxKind::StringLiteralExpr: {
- ContextData.createFromBack(Kind, 1);
+ ContextData.createFromBackTokens(Kind, UsedTokens, 1);
break;
}
@@ -282,17 +309,24 @@
void SyntaxParsingContextChild::makeNodeWhole(SyntaxKind Kind) {
assert(ContextData.Enabled);
+ auto EndLoc = Tok.getLoc();
+ auto AllNodes = ContextData.collectAllSyntax(EndLoc);
switch (Kind) {
+ case SyntaxKind::FunctionCallArgument:
case SyntaxKind::CodeBlock: {
- ContextData.createFromBack(Kind);
+ ContextData.createWhole(Kind, AllNodes);
break;
}
- case SyntaxKind::StmtList: {
- if (ContextData.getPendingSyntax().empty()) {
- // Create an empty statement list if no statement is in the context.
- ContextData.addPendingSyntax({SyntaxFactory::makeBlankStmtList().getRaw()});
+ case SyntaxKind::StmtList:
+ case SyntaxKind::FunctionCallArgumentList: {
+ if (AllNodes.empty()) {
+ // Create an empty argument list if no arguments are in the context.
+ RawSyntaxInfo Empty(SyntaxFactory::
+ makeBlankCollectionSyntax(Kind).getRaw());
+ Empty.setBeforeLoc(EndLoc);
+ ContextData.addPendingSyntax(Empty);
} else {
- ContextData.createFromBack(Kind);
+ ContextData.createWhole(Kind, AllNodes);
}
break;
}
@@ -335,26 +369,22 @@
if (!ContextData.Enabled)
return;
- // Set the end of the context.
- ContextData.setContextEnd(Tok.getLoc());
+ SourceLoc EndLoc = Tok.getLoc();
if (KnownSyntax) {
// If the entire context should be created to a known syntax kind, create
// all pending syntax nodes into that node.
makeNodeWhole(*KnownSyntax);
assert(ContextData.getPendingSyntax().size() == 1);
- auto AllNodes = ContextData.collectAllSyntax();
- assert(AllNodes.size() == 1);
- Parent->ContextData.addPendingSyntax(AllNodes.front());
+ Parent->ContextData.addPendingSyntax(ContextData.getPendingSyntax().front());
return;
}
- auto AllNodes = ContextData.collectAllSyntax();
+ auto AllNodes = ContextData.collectAllSyntax(EndLoc);
RC<RawSyntax> FinalResult;
if (AllNodes.empty())
return;
// Make sure we used all tokens.
- assert(AllNodes.front().getStartLoc() == ContextData.allTokens().front().getStartLoc());
- assert(AllNodes.back().getEndLoc() == ContextData.allTokens().back().getStartLoc());
+ assert(AllNodes.front().getStartLoc() == ContextData.getContextStartLoc());
if (AllNodes.size() == 1) {
// If we have only one syntax node remaining, we are done.
diff --git a/stdlib/public/SwiftShims/HeapObject.h b/stdlib/public/SwiftShims/HeapObject.h
index 29b78b9..8c9ae82 100644
--- a/stdlib/public/SwiftShims/HeapObject.h
+++ b/stdlib/public/SwiftShims/HeapObject.h
@@ -16,8 +16,7 @@
#include "System.h"
#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_64 16
-// TODO: Should be 8
-#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32 12
+#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32 8
#ifdef __cplusplus
#include <type_traits>
@@ -39,12 +38,12 @@
InlineRefCounts refCounts
/// The Swift heap-object header.
+/// This must match RefCountedStructTy in IRGen.
struct HeapObject {
/// This is always a valid pointer to a metadata object.
HeapMetadata const *metadata;
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
- // FIXME: allocate two words of metadata on 32-bit platforms
#ifdef __cplusplus
HeapObject() = default;
@@ -75,15 +74,8 @@
static_assert(std::is_trivially_destructible<HeapObject>::value,
"HeapObject must be trivially destructible");
-// FIXME: small header for 32-bit
-//static_assert(sizeof(HeapObject) == 2*sizeof(void*),
-// "HeapObject must be two pointers long");
-//
-static_assert(sizeof(HeapObject) ==
- (sizeof(void*) == 8 ? SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_64 :
- sizeof(void*) == 4 ? SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32 :
- 0 && "unexpected pointer size"),
- "HeapObject must match ABI heap object header size");
+static_assert(sizeof(HeapObject) == 2*sizeof(void*),
+ "HeapObject must be two pointers long");
static_assert(alignof(HeapObject) == alignof(void*),
"HeapObject must be pointer-aligned");
diff --git a/stdlib/public/SwiftShims/RefCount.h b/stdlib/public/SwiftShims/RefCount.h
index 211de02..e1cd7aa 100644
--- a/stdlib/public/SwiftShims/RefCount.h
+++ b/stdlib/public/SwiftShims/RefCount.h
@@ -15,19 +15,17 @@
#include "Visibility.h"
#include "SwiftStdint.h"
+// This definition is a placeholder for importing into Swift.
+// It provides size and alignment but cannot be manipulated safely there.
+typedef struct {
+ __swift_uintptr_t refCounts SWIFT_ATTRIBUTE_UNAVAILABLE;
+} InlineRefCountsPlaceholder;
+
#if !defined(__cplusplus)
-// These definitions are placeholders for importing into Swift.
-// They provide size and alignment but cannot be manipulated safely there.
+typedef InlineRefCountsPlaceholder InlineRefCounts;
-typedef struct {
- _Alignas(__swift_uintptr_t) __swift_uint32_t refCounts1 SWIFT_ATTRIBUTE_UNAVAILABLE;
- __swift_uint32_t refCounts2 SWIFT_ATTRIBUTE_UNAVAILABLE;
-} InlineRefCounts;
-
-// not __cplusplus
#else
-// __cplusplus
#include <type_traits>
#include <atomic>
@@ -733,11 +731,6 @@
template <typename RefCountBits>
class RefCounts {
std::atomic<RefCountBits> refCounts;
-#if __POINTER_WIDTH__ == 32
- // FIXME: hack - something somewhere is assuming a 3-word header on 32-bit
- // See also other fixmes marked "small header for 32-bit"
- uintptr_t : 32;
-#endif
// Out-of-line slow paths.
@@ -1572,15 +1565,11 @@
#endif
// These assertions apply to both the C and the C++ declarations.
-_Static_assert(_Alignof(InlineRefCounts) == _Alignof(__swift_uintptr_t),
- "InlineRefCounts must be pointer-aligned");
-// FIXME: small header for 32-bit
-#if 0
+_Static_assert(sizeof(InlineRefCounts) == sizeof(InlineRefCountsPlaceholder),
+ "InlineRefCounts and InlineRefCountsPlaceholder must match");
_Static_assert(sizeof(InlineRefCounts) == sizeof(__swift_uintptr_t),
"InlineRefCounts must be pointer-sized");
-#else
-_Static_assert(sizeof(InlineRefCounts) == 2*sizeof(__swift_uint32_t),
- "InlineRefCounts must be 8 bytes");
-#endif
+_Static_assert(_Alignof(InlineRefCounts) == _Alignof(__swift_uintptr_t),
+ "InlineRefCounts must be pointer-aligned");
#endif
diff --git a/stdlib/public/core/Arrays.swift.gyb b/stdlib/public/core/Arrays.swift.gyb
index c9eeeee..773e7fb 100644
--- a/stdlib/public/core/Arrays.swift.gyb
+++ b/stdlib/public/core/Arrays.swift.gyb
@@ -178,7 +178,7 @@
/// can store any kind of elements---from integers to strings to classes.
///
/// Swift makes it easy to create arrays in your code using an array literal:
-/// simply surround a comma separated list of values with square brackets.
+/// simply surround a comma-separated list of values with square brackets.
/// Without any other information, Swift creates an array that includes the
/// specified values, automatically inferring the array's `Element` type. For
/// example:
diff --git a/stdlib/public/core/Builtin.swift b/stdlib/public/core/Builtin.swift
index 72e2592..2f06587 100644
--- a/stdlib/public/core/Builtin.swift
+++ b/stdlib/public/core/Builtin.swift
@@ -144,8 +144,13 @@
return !(lhs == rhs)
}
-/// Returns `true` iff `t0` is identical to `t1`; i.e. if they are both
-/// `nil` or they both represent the same type.
+/// Returns a Boolean value indicating whether two types are identical.
+///
+/// - Parameters:
+/// - t0: A type to compare.
+/// - t1: Another type to compare.
+/// - Returns: `true` if both `t0` and `t1` are `nil` or if they represent the
+/// same type; otherwise, `false`.
@_inlineable
public func == (t0: Any.Type?, t1: Any.Type?) -> Bool {
switch (t0, t1) {
@@ -156,8 +161,13 @@
}
}
-/// Returns `false` iff `t0` is identical to `t1`; i.e. if they are both
-/// `nil` or they both represent the same type.
+/// Returns a Boolean value indicating whether two types are not identical.
+///
+/// - Parameters:
+/// - t0: A type to compare.
+/// - t1: Another type to compare.
+/// - Returns: `true` if one, but not both, of `t0` and `t1` are `nil`, or if
+/// they represent different types; otherwise, `false`.
@_inlineable
public func != (t0: Any.Type?, t1: Any.Type?) -> Bool {
return !(t0 == t1)
diff --git a/stdlib/public/core/CTypes.swift b/stdlib/public/core/CTypes.swift
index 018b1da..0d3af0d 100644
--- a/stdlib/public/core/CTypes.swift
+++ b/stdlib/public/core/CTypes.swift
@@ -42,17 +42,19 @@
/// The C 'int' type.
public typealias CInt = Int32
-/// The C 'long' type.
#if os(Windows) && arch(x86_64)
+/// The C 'long' type.
public typealias CLong = Int32
#else
+/// The C 'long' type.
public typealias CLong = Int
#endif
-/// The C 'long long' type.
#if os(Windows) && arch(x86_64)
+/// The C 'long long' type.
public typealias CLongLong = Int
#else
+/// The C 'long long' type.
public typealias CLongLong = Int64
#endif
@@ -200,7 +202,7 @@
}
}
-/// The corresponding Swift type to `va_list` in imported C APIs.
+/// A wrapper around a C `va_list` pointer.
@_fixed_layout
public struct CVaListPointer {
@_versioned // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/Codable.swift b/stdlib/public/core/Codable.swift
index 462c6cc..e7e2e05 100644
--- a/stdlib/public/core/Codable.swift
+++ b/stdlib/public/core/Codable.swift
@@ -1166,8 +1166,8 @@
// An implementation of _KeyedDecodingContainerBase and _KeyedDecodingContainerBox are given at the bottom of this file.
-/// A concrete container that provides a view into an decoder's storage, making
-/// the encoded properties of an decodable type accessible by keys.
+/// A concrete container that provides a view into a decoder's storage, making
+/// the encoded properties of a decodable type accessible by keys.
@_fixed_layout // FIXME(sil-serialize-all)
public struct KeyedDecodingContainer<K : CodingKey> : KeyedDecodingContainerProtocol {
public typealias Key = K
@@ -2307,7 +2307,8 @@
mutating func encode<T : Encodable>(_ value: T) throws
}
-/// A `SingleValueDecodingContainer` is a container which can support the storage and direct decoding of a single non-keyed value.
+/// A container that can support the storage and direct decoding of a single
+/// nonkeyed value.
public protocol SingleValueDecodingContainer {
/// The path of coding keys taken to get to this point in encoding.
var codingPath: [CodingKey] { get }
diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index 567c036..3861ca5 100644
--- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -1503,8 +1503,9 @@
public init?(exactly value: ${That}) {
_value = Builtin.${sign}itofp_${ThatBuiltinName}_FPIEEE${bits}(value._value)
-% if srcBits < SignificandBitCount:
- if ${That}(self) != value {
+% if srcBits >= SignificandBitCount:
+ guard let roundTrip = ${That}(exactly: self),
+ roundTrip == value else {
return nil
}
% end
diff --git a/stdlib/public/core/KeyPath.swift b/stdlib/public/core/KeyPath.swift
index 020ff15..2f8a39d 100644
--- a/stdlib/public/core/KeyPath.swift
+++ b/stdlib/public/core/KeyPath.swift
@@ -1620,8 +1620,8 @@
// on `Self` to prevent dynamically-typed methods from being inherited by
// statically-typed key paths.
-/// This protocol is an implementation detail of key path expressions; do not
-/// use it directly.
+/// An implementation detail of key path expressions; do not use this protocol
+/// directly.
@_show_in_interface
public protocol _AppendKeyPath {}
diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift
index 1f41bd5..92f5b09 100644
--- a/stdlib/public/core/Mirror.swift
+++ b/stdlib/public/core/Mirror.swift
@@ -12,15 +12,31 @@
// FIXME: ExistentialCollection needs to be supported before this will work
// without the ObjC Runtime.
-/// Representation of the sub-structure and optional "display style"
-/// of any arbitrary subject instance.
+/// A representation of the substructure and display style of an instance of
+/// any type.
///
-/// Describes the parts---such as stored properties, collection
-/// elements, tuple elements, or the active enumeration case---that
-/// make up a particular instance. May also supply a "display style"
-/// property that suggests how this structure might be rendered.
+/// A mirror describes the parts that make up a particular instance, such as
+/// the instance's stored properties, collection or tuple elements, or its
+/// active enumeration case. Mirrors also provide a "display style" property
+/// that suggests how this mirror might be rendered.
///
-/// Mirrors are used by playgrounds and the debugger.
+/// Playgrounds and the debugger use the `Mirror` type to display
+/// representations of values of any type. For example, when you pass an
+/// instance to the `dump(_:_:_:_:)` function, a mirror is used to render that
+/// instance's runtime contents.
+///
+/// struct Point {
+/// let x: Int, y: Int
+/// }
+///
+/// let p = Point(x: 21, y: 30)
+/// print(String(reflecting: p))
+/// // Prints "â–¿ Point
+/// // - x: 21
+/// // - y: 30"
+///
+/// To customize the mirror representation of a custom type, add conformance to
+/// the `CustomReflectable` protocol.
@_fixed_layout // FIXME(sil-serialize-all)
public struct Mirror {
/// Representation of descendant classes that don't override
@@ -46,56 +62,58 @@
case suppressed
}
- /// Representation of ancestor classes.
+ /// The representation to use for ancestor classes.
///
- /// A `CustomReflectable` class can control how its mirror will
- /// represent ancestor classes by initializing the mirror with a
- /// `AncestorRepresentation`. This setting has no effect on mirrors
+ /// A class that conforms to the `CustomReflectable` protocol can control how
+ /// its mirror represents ancestor classes by initializing the mirror
+ /// with an `AncestorRepresentation`. This setting has no effect on mirrors
/// reflecting value type instances.
public enum AncestorRepresentation {
- /// Generate a default mirror for all ancestor classes.
+ /// Generates a default mirror for all ancestor classes.
///
- /// This case is the default.
+ /// This case is the default when initializing a `Mirror` instance.
///
- /// - Note: This option generates default mirrors even for
- /// ancestor classes that may implement `CustomReflectable`'s
- /// `customMirror` requirement. To avoid dropping an ancestor class
- /// customization, an override of `customMirror` should pass
- /// `ancestorRepresentation: .Customized(super.customMirror)` when
- /// initializing its `Mirror`.
+ /// When you use this option, a subclass's mirror generates default mirrors
+ /// even for ancestor classes that conform to the `CustomReflectable`
+ /// protocol. To avoid dropping the customization provided by ancestor
+ /// classes, an override of `customMirror` should pass
+ /// `.customized({ super.customMirror })` as `ancestorRepresentation` when
+ /// initializing its mirror.
case generated
- /// Use the nearest ancestor's implementation of `customMirror` to
- /// create a mirror for that ancestor. Other classes derived from
- /// such an ancestor are given a default mirror.
+ /// Uses the nearest ancestor's implementation of `customMirror` to create
+ /// a mirror for that ancestor.
///
- /// The payload for this option should always be
- /// "`{ super.customMirror }`":
+ /// Other classes derived from such an ancestor are given a default mirror.
+ /// The payload for this option should always be `{ super.customMirror }`:
///
/// var customMirror: Mirror {
- /// return Mirror(
- /// self,
- /// children: ["someProperty": self.someProperty],
- /// ancestorRepresentation: .Customized({ super.customMirror })) // <==
+ /// return Mirror(
+ /// self,
+ /// children: ["someProperty": self.someProperty],
+ /// ancestorRepresentation: .customized({ super.customMirror })) // <==
/// }
case customized(() -> Mirror)
- /// Suppress the representation of all ancestor classes. The
- /// resulting `Mirror`'s `superclassMirror` is `nil`.
+ /// Suppresses the representation of all ancestor classes.
+ ///
+ /// In a mirror created with this ancestor representation, the
+ /// `superclassMirror` property is `nil`.
case suppressed
}
- /// Reflect upon the given `subject`.
+ /// Creates a mirror that reflects on the given instance.
///
- /// If the dynamic type of `subject` conforms to `CustomReflectable`,
- /// the resulting mirror is determined by its `customMirror` property.
+ /// If the dynamic type of `subject` conforms to `CustomReflectable`, the
+ /// resulting mirror is determined by its `customMirror` property.
/// Otherwise, the result is generated by the language.
///
- /// - Note: If the dynamic type of `subject` has value semantics,
- /// subsequent mutations of `subject` will not observable in
- /// `Mirror`. In general, though, the observability of such
- /// mutations is unspecified.
+ /// If the dynamic type of `subject` has value semantics, subsequent
+ /// mutations of `subject` will not observable in `Mirror`. In general,
+ /// though, the observability of mutations is unspecified.
+ ///
+ /// - Parameter subject: The instance for which to create a mirror.
@_inlineable // FIXME(sil-serialize-all)
public init(reflecting subject: Any) {
if case let customized as CustomReflectable = subject {
@@ -107,36 +125,33 @@
}
}
- /// An element of the reflected instance's structure. The optional
- /// `label` may be used when appropriate, e.g. to represent the name
- /// of a stored property or of an active `enum` case, and will be
- /// used for lookup when `String`s are passed to the `descendant`
- /// method.
+ /// An element of the reflected instance's structure.
+ ///
+ /// When the `label` component in not `nil`, it may represent the name of a
+ /// stored property or an active `enum` case. If you pass strings to the
+ /// `descendant(_:_:)` method, labels are used for lookup.
public typealias Child = (label: String?, value: Any)
- /// The type used to represent sub-structure.
+ /// The type used to represent substructure.
///
- /// Depending on your needs, you may find it useful to "upgrade"
- /// instances of this type to `AnyBidirectionalCollection` or
- /// `AnyRandomAccessCollection`. For example, to display the last
- /// 20 children of a mirror if they can be accessed efficiently, you
- /// might write:
+ /// When working with a mirror that reflects a bidirectional or random access
+ /// collection, you may find it useful to "upgrade" instances of this type
+ /// to `AnyBidirectionalCollection` or `AnyRandomAccessCollection`. For
+ /// example, to display the last twenty children of a mirror if they can be
+ /// accessed efficiently, you write the following code:
///
/// if let b = AnyBidirectionalCollection(someMirror.children) {
- /// var i = xs.index(b.endIndex, offsetBy: -20,
- /// limitedBy: b.startIndex) ?? b.startIndex
- /// while i != xs.endIndex {
- /// print(b[i])
- /// b.formIndex(after: &i)
- /// }
+ /// for element in b.suffix(20) {
+ /// print(element)
+ /// }
/// }
public typealias Children = AnyCollection<Child>
- /// A suggestion of how a `Mirror`'s `subject` is to be interpreted.
+ /// A suggestion of how a mirror's subject is to be interpreted.
///
/// Playgrounds and the debugger will show a representation similar
/// to the one used for instances of the kind indicated by the
- /// `DisplayStyle` case name when the `Mirror` is used for display.
+ /// `DisplayStyle` case name when the mirror is used for display.
@_fixed_layout // FIXME(sil-serialize-all)
public enum DisplayStyle {
case `struct`, `class`, `enum`, tuple, optional, collection
@@ -200,26 +215,31 @@
return Mirror._noSuperclassMirror
}
- /// Represent `subject` with structure described by `children`,
- /// using an optional `displayStyle`.
+ /// Creates a mirror representing the given subject with a specified
+ /// structure.
///
- /// If `subject` is not a class instance, `ancestorRepresentation`
- /// is ignored. Otherwise, `ancestorRepresentation` determines
+ /// You use this initializer from within your type's `customMirror`
+ /// implementation to create a customized mirror.
+ ///
+ /// If `subject` is a class instance, `ancestorRepresentation` determines
/// whether ancestor classes will be represented and whether their
- /// `customMirror` implementations will be used. By default, a
- /// representation is automatically generated and any `customMirror`
- /// implementation is bypassed. To prevent bypassing customized
- /// ancestors, `customMirror` overrides should initialize the
- /// `Mirror` with:
+ /// `customMirror` implementations will be used. By default, the
+ /// `customMirror` implementation of any ancestors is ignored. To prevent
+ /// bypassing customized ancestors, pass
+ /// `.customized({ super.customMirror })` as the `ancestorRepresentation`
+ /// parameter when implementing your type's `customMirror` property.
///
- /// ancestorRepresentation: .customized({ super.customMirror })
- ///
- /// - Note: The traversal protocol modeled by `children`'s indices
- /// (`ForwardIndex`, `BidirectionalIndex`, or
- /// `RandomAccessIndex`) is captured so that the resulting
- /// `Mirror`'s `children` may be upgraded later. See the failable
- /// initializers of `AnyBidirectionalCollection` and
- /// `AnyRandomAccessCollection` for details.
+ /// - Parameters:
+ /// - subject: The instance to represent in the new mirror.
+ /// - children: The structure to use for the mirror. The collection
+ /// traversal modeled by `children` is captured so that the resulting
+ /// mirror's children may be upgraded to a bidirectional or random
+ /// access collection later. See the `children` property for details.
+ /// - displayStyle: The preferred display style for the mirror when
+ /// presented in the debugger or in a playground. The default is `nil`.
+ /// - ancestorRepresentation: The means of generating the subject's
+ /// ancestor representation. `ancestorRepresentation` is ignored if
+ /// `subject` is not a class instance. The default is `.generated`.
@_inlineable // FIXME(sil-serialize-all)
public init<Subject, C : Collection>(
_ subject: Subject,
@@ -239,36 +259,33 @@
= subject is CustomLeafReflectable ? .suppressed : .generated
}
- /// Represent `subject` with child values given by
- /// `unlabeledChildren`, using an optional `displayStyle`. The
- /// result's child labels will all be `nil`.
+ /// Creates a mirror representing the given subject with unlabeled children.
///
- /// This initializer is especially useful for the mirrors of
- /// collections, e.g.:
+ /// You use this initializer from within your type's `customMirror`
+ /// implementation to create a customized mirror, particularly for custom
+ /// types that are collections. The labels of the resulting mirror's
+ /// `children` collection are all `nil`.
///
- /// extension MyArray : CustomReflectable {
- /// var customMirror: Mirror {
- /// return Mirror(self, unlabeledChildren: self, displayStyle: .collection)
- /// }
- /// }
- ///
- /// If `subject` is not a class instance, `ancestorRepresentation`
- /// is ignored. Otherwise, `ancestorRepresentation` determines
+ /// If `subject` is a class instance, `ancestorRepresentation` determines
/// whether ancestor classes will be represented and whether their
- /// `customMirror` implementations will be used. By default, a
- /// representation is automatically generated and any `customMirror`
- /// implementation is bypassed. To prevent bypassing customized
- /// ancestors, `customMirror` overrides should initialize the
- /// `Mirror` with:
+ /// `customMirror` implementations will be used. By default, the
+ /// `customMirror` implementation of any ancestors is ignored. To prevent
+ /// bypassing customized ancestors, pass
+ /// `.customized({ super.customMirror })` as the `ancestorRepresentation`
+ /// parameter when implementing your type's `customMirror` property.
///
- /// ancestorRepresentation: .Customized({ super.customMirror })
- ///
- /// - Note: The traversal protocol modeled by `children`'s indices
- /// (`ForwardIndex`, `BidirectionalIndex`, or
- /// `RandomAccessIndex`) is captured so that the resulting
- /// `Mirror`'s `children` may be upgraded later. See the failable
- /// initializers of `AnyBidirectionalCollection` and
- /// `AnyRandomAccessCollection` for details.
+ /// - Parameters:
+ /// - subject: The instance to represent in the new mirror.
+ /// - unlabeledChildren: The children to use for the mirror. The collection
+ /// traversal modeled by `unlabeledChildren` is captured so that the
+ /// resulting mirror's children may be upgraded to a bidirectional or
+ /// random access collection later. See the `children` property for
+ /// details.
+ /// - displayStyle: The preferred display style for the mirror when
+ /// presented in the debugger or in a playground. The default is `nil`.
+ /// - ancestorRepresentation: The means of generating the subject's
+ /// ancestor representation. `ancestorRepresentation` is ignored if
+ /// `subject` is not a class instance. The default is `.generated`.
@_inlineable // FIXME(sil-serialize-all)
public init<Subject, C : Collection>(
_ subject: Subject,
@@ -291,29 +308,35 @@
= subject is CustomLeafReflectable ? .suppressed : .generated
}
- /// Represent `subject` with labeled structure described by
- /// `children`, using an optional `displayStyle`.
+ /// Creates a mirror representing the given subject using a dictionary
+ /// literal for the structure.
///
- /// Pass a dictionary literal with `String` keys as `children`. Be
- /// aware that although an *actual* `Dictionary` is
- /// arbitrarily-ordered, the ordering of the `Mirror`'s `children`
- /// will exactly match that of the literal you pass.
+ /// You use this initializer from within your type's `customMirror`
+ /// implementation to create a customized mirror. Pass a dictionary literal
+ /// with string keys as `children`. Although an *actual* dictionary is
+ /// arbitrarily-ordered, when you create a mirror with a dictionary literal,
+ /// the ordering of the mirror's `children` will exactly match that of the
+ /// literal you pass.
///
- /// If `subject` is not a class instance, `ancestorRepresentation`
- /// is ignored. Otherwise, `ancestorRepresentation` determines
+ /// If `subject` is a class instance, `ancestorRepresentation` determines
/// whether ancestor classes will be represented and whether their
- /// `customMirror` implementations will be used. By default, a
- /// representation is automatically generated and any `customMirror`
- /// implementation is bypassed. To prevent bypassing customized
- /// ancestors, `customMirror` overrides should initialize the
- /// `Mirror` with:
+ /// `customMirror` implementations will be used. By default, the
+ /// `customMirror` implementation of any ancestors is ignored. To prevent
+ /// bypassing customized ancestors, pass
+ /// `.customized({ super.customMirror })` as the `ancestorRepresentation`
+ /// parameter when implementing your type's `customMirror` property.
///
- /// ancestorRepresentation: .customized({ super.customMirror })
- ///
- /// - Note: The resulting `Mirror`'s `children` may be upgraded to
- /// `AnyRandomAccessCollection` later. See the failable
- /// initializers of `AnyBidirectionalCollection` and
- /// `AnyRandomAccessCollection` for details.
+ /// - Parameters:
+ /// - subject: The instance to represent in the new mirror.
+ /// - children: A dictionary literal to use as the structure for the
+ /// mirror. The `children` collection of the resulting mirror may be
+ /// upgraded to a random access collection later. See the `children`
+ /// property for details.
+ /// - displayStyle: The preferred display style for the mirror when
+ /// presented in the debugger or in a playground. The default is `nil`.
+ /// - ancestorRepresentation: The means of generating the subject's
+ /// ancestor representation. `ancestorRepresentation` is ignored if
+ /// `subject` is not a class instance. The default is `.generated`.
@_inlineable // FIXME(sil-serialize-all)
public init<Subject>(
_ subject: Subject,
@@ -335,7 +358,7 @@
/// The static type of the subject being reflected.
///
- /// This type may differ from the subject's dynamic type when `self`
+ /// This type may differ from the subject's dynamic type when this mirror
/// is the `superclassMirror` of another mirror.
public let subjectType: Any.Type
@@ -343,9 +366,10 @@
/// reflected subject.
public let children: Children
- /// Suggests a display style for the reflected subject.
+ /// A suggested display style for the reflected subject.
public let displayStyle: DisplayStyle?
+ /// A mirror of the subject's superclass, if one exists.
@_inlineable // FIXME(sil-serialize-all)
public var superclassMirror: Mirror? {
return _makeSuperclassMirror()
@@ -359,7 +383,7 @@
/// A type that explicitly supplies its own mirror.
///
-/// You can create a mirror for any type using the `Mirror(reflect:)`
+/// You can create a mirror for any type using the `Mirror(reflecting:)`
/// initializer, but if you are not satisfied with the mirror supplied for
/// your type by default, you can make it conform to `CustomReflectable` and
/// return a custom `Mirror` instance.
@@ -383,9 +407,10 @@
///
/// Do not declare new conformances to this protocol; they will not
/// work as expected.
-// FIXME(ABI)#49 (Sealed Protocols): this protocol should be "non-open" and you shouldn't be able to
-// create conformances.
-public protocol MirrorPath {}
+public protocol MirrorPath {
+ // FIXME(ABI)#49 (Sealed Protocols): this protocol should be "non-open" and
+ // you shouldn't be able to create conformances.
+}
extension Int : MirrorPath {}
extension String : MirrorPath {}
@@ -405,42 +430,50 @@
internal var customMirror: Mirror { return mirror }
}
- /// Return a specific descendant of the reflected subject, or `nil`
- /// Returns a specific descendant of the reflected subject, or `nil`
- /// if no such descendant exists.
+ /// Returns a specific descendant of the reflected subject, or `nil` if no
+ /// such descendant exists.
///
- /// A `String` argument selects the first `Child` with a matching label.
- /// An integer argument *n* select the *n*th `Child`. For example:
+ /// Pass a variadic list of string and integer arguments. Each string
+ /// argument selects the first child with a matching label. Each integer
+ /// argument selects the child at that offset. For example, passing
+ /// `1, "two", 3` as arguments to `myMirror.descendant(_:_:)` is equivalent
+ /// to:
///
- /// var d = Mirror(reflecting: x).descendant(1, "two", 3)
- ///
- /// is equivalent to:
- ///
- /// var d = nil
- /// let children = Mirror(reflecting: x).children
- /// if let p0 = children.index(children.startIndex,
- /// offsetBy: 1, limitedBy: children.endIndex) {
- /// let grandChildren = Mirror(reflecting: children[p0].value).children
- /// SeekTwo: for g in grandChildren {
- /// if g.label == "two" {
- /// let greatGrandChildren = Mirror(reflecting: g.value).children
- /// if let p1 = greatGrandChildren.index(
- /// greatGrandChildren.startIndex,
- /// offsetBy: 3, limitedBy: greatGrandChildren.endIndex) {
- /// d = greatGrandChildren[p1].value
- /// }
- /// break SeekTwo
+ /// var result: Any? = nil
+ /// let children = myMirror.children
+ /// if let i0 = children.index(
+ /// children.startIndex, offsetBy: 1, limitedBy: children.endIndex),
+ /// i0 != children.endIndex
+ /// {
+ /// let grandChildren = Mirror(reflecting: children[i0].value).children
+ /// if let i1 = grandChildren.index(where: { $0.label == "two" }) {
+ /// let greatGrandChildren =
+ /// Mirror(reflecting: grandChildren[i1].value).children
+ /// if let i2 = greatGrandChildren.index(
+ /// greatGrandChildren.startIndex,
+ /// offsetBy: 3,
+ /// limitedBy: greatGrandChildren.endIndex),
+ /// i2 != greatGrandChildren.endIndex
+ /// {
+ /// // Success!
+ /// result = greatGrandChildren[i2].value
+ /// }
/// }
- /// }
/// }
///
- /// As you can see, complexity for each element of the argument list
- /// depends on the argument type and capabilities of the collection
- /// used to initialize the corresponding subject's parent's mirror.
- /// Each `String` argument results in a linear search. In short,
- /// this function is suitable for exploring the structure of a
- /// `Mirror` in a REPL or playground, but don't expect it to be
- /// efficient.
+ /// This function is suitable for exploring the structure of a mirror in a
+ /// REPL or playground, but is not intended to be efficient. The efficiency
+ /// of finding each element in the argument list depends on the argument
+ /// type and the capabilities of the each level of the mirror's `children`
+ /// collections. Each string argument requires a linear search, and unless
+ /// the underlying collection supports random-access traversal, each integer
+ /// argument also requires a linear operation.
+ ///
+ /// - Parameters:
+ /// - first: The first mirror path component to access.
+ /// - rest: Any remaining mirror path components.
+ /// - Returns: The descendant of this mirror specified by the given mirror
+ /// path components if such a descendant exists; otherwise, `nil`.
@_inlineable // FIXME(sil-serialize-all)
public func descendant(
_ first: MirrorPath, _ rest: MirrorPath...
@@ -698,19 +731,20 @@
}
extension PlaygroundQuickLook {
- /// Initialize for the given `subject`.
+ /// Creates a new Quick Look for the given instance.
///
/// If the dynamic type of `subject` conforms to
- /// `CustomPlaygroundQuickLookable`, returns the result of calling
- /// its `customPlaygroundQuickLook` property. Otherwise, returns
- /// a `PlaygroundQuickLook` synthesized for `subject` by the
- /// language. Note that in some cases the result may be
- /// `.Text(String(reflecting: subject))`.
+ /// `CustomPlaygroundQuickLookable`, the result is found by calling its
+ /// `customPlaygroundQuickLook` property. Otherwise, the result is
+ /// synthesized by the language. In some cases, the synthesized result may
+ /// be `.text(String(reflecting: subject))`.
///
- /// - Note: If the dynamic type of `subject` has value semantics,
- /// subsequent mutations of `subject` will not observable in
- /// `Mirror`. In general, though, the observability of such
- /// mutations is unspecified.
+ /// - Note: If the dynamic type of `subject` has value semantics, subsequent
+ /// mutations of `subject` will not observable in the Quick Look. In
+ /// general, though, the observability of such mutations is unspecified.
+ ///
+ /// - Parameter subject: The instance to represent with the resulting Quick
+ /// Look.
@_inlineable // FIXME(sil-serialize-all)
public init(reflecting subject: Any) {
if let customized = subject as? CustomPlaygroundQuickLookable {
diff --git a/stdlib/public/core/Policy.swift b/stdlib/public/core/Policy.swift
index e4649b7..8128f8c 100644
--- a/stdlib/public/core/Policy.swift
+++ b/stdlib/public/core/Policy.swift
@@ -15,8 +15,8 @@
//===----------------------------------------------------------------------===//
// Standardized uninhabited type
//===----------------------------------------------------------------------===//
-/// The return type of functions that do not return normally; a type with no
-/// values.
+/// The return type of functions that do not return normally, that is, a type
+/// with no values.
///
/// Use `Never` as the return type when declaring a closure, function, or
/// method that unconditionally throws an error, traps, or otherwise does
@@ -31,16 +31,16 @@
//===----------------------------------------------------------------------===//
// Standardized aliases
//===----------------------------------------------------------------------===//
-/// The return type of functions that don't explicitly specify a return type;
-/// an empty tuple (i.e., `()`).
+/// The return type of functions that don't explicitly specify a return type,
+/// that is, an empty tuple `()`.
///
/// When declaring a function or method, you don't need to specify a return
/// type if no value will be returned. However, the type of a function,
/// method, or closure always includes a return type, which is `Void` if
/// otherwise unspecified.
///
-/// Use `Void` or an empty tuple as the return type when declaring a
-/// closure, function, or method that doesn't return a value.
+/// Use `Void` or an empty tuple as the return type when declaring a closure,
+/// function, or method that doesn't return a value.
///
/// // No return type declared:
/// func logMessage(_ s: String) {
diff --git a/stdlib/public/core/Sort.swift.gyb b/stdlib/public/core/Sort.swift.gyb
index b59c8cb..f7992d1 100644
--- a/stdlib/public/core/Sort.swift.gyb
+++ b/stdlib/public/core/Sort.swift.gyb
@@ -406,9 +406,15 @@
% end
// for p in preds
-/// Exchange the values of `a` and `b`.
+/// Exchanges the values of the two arguments.
///
-/// - Precondition: `a` and `b` do not alias each other.
+/// The two arguments must not alias each other. To swap two elements of a
+/// mutable collection, use the `swapAt(_:_:)` method of that collection
+/// instead of this function.
+///
+/// - Parameters:
+/// - a: The first value to swap.
+/// - b: The second value to swap.
@_inlineable
public func swap<T>(_ a: inout T, _ b: inout T) {
// Semantically equivalent to (a, b) = (b, a).
diff --git a/stdlib/public/core/String.swift b/stdlib/public/core/String.swift
index 7552225..7339112 100644
--- a/stdlib/public/core/String.swift
+++ b/stdlib/public/core/String.swift
@@ -48,7 +48,7 @@
/// encoding.
///
/// - Parameters:
- /// - codeUnits: A collection of code units encoded in the ecoding
+ /// - codeUnits: A collection of code units encoded in the encoding
/// specified in `sourceEncoding`.
/// - sourceEncoding: The encoding in which `codeUnits` should be
/// interpreted.
@@ -280,7 +280,7 @@
/// encoding.
///
/// - Parameters:
- /// - codeUnits: A collection of code units encoded in the ecoding
+ /// - codeUnits: A collection of code units encoded in the encoding
/// specified in `sourceEncoding`.
/// - sourceEncoding: The encoding in which `codeUnits` should be
/// interpreted.
@@ -673,6 +673,12 @@
@_fixed_layout
public struct String {
/// Creates an empty string.
+ ///
+ /// Using this initializer is equivalent to initializing a string with an
+ /// empty string literal.
+ ///
+ /// let empty = ""
+ /// let alsoEmpty = String()
@_inlineable // FIXME(sil-serialize-all)
public init() {
_core = _StringCore()
diff --git a/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb b/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
index 6be2abd..5af0bcd 100644
--- a/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
+++ b/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
@@ -29,6 +29,11 @@
/// let zeroes = String(repeating: "0" as Character, count: 10)
/// print(zeroes)
/// // Prints "0000000000"
+ ///
+ /// - Parameters:
+ /// - repeatedValue: The character to repeat.
+ /// - count: The number of times to repeat `repeatedValue` in the
+ /// resulting string.
@_inlineable // FIXME(sil-serialize-all)
public init(repeating repeatedValue: Character, count: Int) {
self.init(repeating: String(repeatedValue), count: count)
@@ -38,6 +43,22 @@
// that String conforms to Collection:
// - init<T>(_ value: T) where T : LosslessStringConvertible
// - init<S>(_ characters: S) where S : Sequence, S.Element == Character
+
+ /// Creates a new string containing the characters in the given sequence.
+ ///
+ /// You can use this initializer to create a new string from the result of
+ /// one or more collection operations on a string's characters. For example:
+ ///
+ /// let str = "The rain in Spain stays mainly in the plain."
+ ///
+ /// let vowels: Set<Character> = ["a", "e", "i", "o", "u"]
+ /// let disemvoweled = String(str.lazy.filter { !vowels.contains($0) })
+ ///
+ /// print(disemvoweled)
+ /// // Prints "Th rn n Spn stys mnly n th pln."
+ ///
+ /// - Parameter other: A string instance or another sequence of
+ /// characters.
@_inlineable // FIXME(sil-serialize-all)
public init<S : Sequence & LosslessStringConvertible>(_ other: S)
where S.Element == Character {
@@ -171,14 +192,16 @@
/// Accesses the character at the given position.
///
- /// Indices for a subscripting a string are shared with the string's
- /// `characters` view. For example:
+ /// You can use the same indices for subscripting a string and its substring.
+ /// For example, this code finds the first letter after the first space:
///
- /// let greeting = "Hello, friend!"
- /// if let i = greeting.characters.index(where: { $0 >= "A" && $0 <= "Z" }) {
- /// print("First capital letter: \(greeting[i])")
+ /// let str = "Greetings, friend! How are you?"
+ /// let firstSpace = str.index(of: " ") ?? str.endIndex
+ /// let substr = str[firstSpace...]
+ /// if let nextCapital = substr.index(where: { $0 >= "A" && $0 <= "Z" }) {
+ /// print("Capital after a space: \(str[nextCapital])")
/// }
- /// // Prints "First capital letter: H"
+ /// // Prints "Capital after a space: H"
///
/// - Parameter i: A valid index of the string. `i` must be less than the
/// string's end index.
@@ -190,17 +213,18 @@
/// Creates a new string containing the characters in the given sequence.
///
/// You can use this initializer to create a new string from the result of
- /// one or more operations on a string's `characters` view. For example:
+ /// one or more collection operations on a string's characters. For example:
///
/// let str = "The rain in Spain stays mainly in the plain."
///
/// let vowels: Set<Character> = ["a", "e", "i", "o", "u"]
- /// let disemvoweled = String(str.characters.lazy.filter { !vowels.contains($0) })
+ /// let disemvoweled = String(str.lazy.filter { !vowels.contains($0) })
///
/// print(disemvoweled)
/// // Prints "Th rn n Spn stys mnly n th pln."
///
- /// - Parameter characters: A sequence of characters.
+ /// - Parameter characters: A string instance or another sequence of
+ /// characters.
@_inlineable // FIXME(sil-serialize-all)
public init<S : Sequence>(_ characters: S)
where S.Iterator.Element == Character {
@@ -326,7 +350,7 @@
/// removes the hyphen from the middle of a string.
///
/// var nonempty = "non-empty"
- /// if let i = nonempty.characters.index(of: "-") {
+ /// if let i = nonempty.index(of: "-") {
/// nonempty.remove(at: i)
/// }
/// print(nonempty)
diff --git a/stdlib/public/core/Substring.swift.gyb b/stdlib/public/core/Substring.swift.gyb
index 4c6208d..8c0f007 100644
--- a/stdlib/public/core/Substring.swift.gyb
+++ b/stdlib/public/core/Substring.swift.gyb
@@ -205,7 +205,7 @@
/// encoding.
///
/// - Parameters:
- /// - codeUnits: A collection of code units encoded in the ecoding
+ /// - codeUnits: A collection of code units encoded in the encoding
/// specified in `sourceEncoding`.
/// - sourceEncoding: The encoding in which `codeUnits` should be
/// interpreted.
diff --git a/stdlib/public/core/UnsafeBufferPointer.swift.gyb b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
index 9b29437..0541c78 100644
--- a/stdlib/public/core/UnsafeBufferPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
@@ -42,7 +42,7 @@
% for mutable in (True, False):
% Self = 'UnsafeMutableBufferPointer' if mutable else 'UnsafeBufferPointer'
% Mutable = 'Mutable' if mutable else ''
-/// A non-owning collection interface to a buffer of ${Mutable.lower()}
+/// A nonowning collection interface to a buffer of ${Mutable.lower()}
/// elements stored contiguously in memory.
///
/// You can use an `${Self}` instance in low level operations to eliminate
diff --git a/stdlib/public/core/VarArgs.swift b/stdlib/public/core/VarArgs.swift
index cffeb4f..d80f6be 100644
--- a/stdlib/public/core/VarArgs.swift
+++ b/stdlib/public/core/VarArgs.swift
@@ -10,28 +10,30 @@
//
//===----------------------------------------------------------------------===//
-/// Instances of conforming types can be encoded, and appropriately
-/// passed, as elements of a C `va_list`.
+/// A type whose instances can be encoded, and appropriately passed, as
+/// elements of a C `va_list`.
///
-/// This protocol is useful in presenting C "varargs" APIs natively in
-/// Swift. It only works for APIs that have a `va_list` variant, so
-/// for example, it isn't much use if all you have is:
+/// You use this protocol to present a native Swift interface to a C "varargs"
+/// API. For example, a program can import a C API like the one defined here:
///
-/// ~~~ c
-/// int c_api(int n, ...)
-/// ~~~
-///
-/// Given a version like this, though,
-///
-/// ~~~ c
+/// ~~~c
/// int c_api(int, va_list arguments)
/// ~~~
///
-/// you can write:
+/// To create a wrapper for the `c_api` function, write a function that takes
+/// `CVarArg` arguments, and then call the imported C function using the
+/// `withVaList(_:_:)` function:
///
/// func swiftAPI(_ x: Int, arguments: CVarArg...) -> Int {
-/// return withVaList(arguments) { c_api(x, $0) }
+/// return withVaList(arguments) { c_api(x, $0) }
/// }
+///
+/// Swift only imports C variadic functions that use a `va_list` for their
+/// arguments. C functions that use the `...` syntax for variadic arguments
+/// are not imported, and therefore can't be called using `CVarArg` arguments.
+///
+/// - Note: Declaring conformance to the `CVarArg` protocol for types defined
+/// outside the standard library is not supported.
public protocol CVarArg {
// Note: the protocol is public, but its requirement is stdlib-private.
// That's because there are APIs operating on CVarArg instances, but
diff --git a/test/Generics/validate_stdlib_generic_signatures.swift b/test/Generics/validate_stdlib_generic_signatures.swift
new file mode 100644
index 0000000..eae4985
--- /dev/null
+++ b/test/Generics/validate_stdlib_generic_signatures.swift
@@ -0,0 +1,6 @@
+// Verifies that all of the generic signatures in the standard library are
+// minimal and canonical.
+
+// RUN: %target-typecheck-verify-swift -typecheck %s -verify-generic-signatures Swift
+
+// expected-no-diagnostics
diff --git a/test/IRGen/class_resilience.swift b/test/IRGen/class_resilience.swift
index e7c2b20..5a4851d 100644
--- a/test/IRGen/class_resilience.swift
+++ b/test/IRGen/class_resilience.swift
@@ -13,14 +13,14 @@
// CHECK: @_T016class_resilience33ClassWithResilientlySizedPropertyC1r16resilient_struct9RectangleVvpWvd = {{(protected )?}}global [[INT]] 0
// CHECK: @_T016class_resilience33ClassWithResilientlySizedPropertyC5colors5Int32VvpWvd = {{(protected )?}}global [[INT]] 0
-// CHECK: @_T016class_resilience14ResilientChildC5fields5Int32VvpWvd = {{(protected )?}}global [[INT]] {{12|16}}
+// CHECK: @_T016class_resilience14ResilientChildC5fields5Int32VvpWvd = {{(protected )?}}global [[INT]] {{8|16}}
// CHECK: @_T016class_resilience21ResilientGenericChildC5fields5Int32VvpWvi = {{(protected )?}}global [[INT]] {{56|88}}
-// CHECK: @_T016class_resilience28ClassWithMyResilientPropertyC1rAA0eF6StructVvpWvd = {{(protected )?}}constant [[INT]] {{12|16}}
-// CHECK: @_T016class_resilience28ClassWithMyResilientPropertyC5colors5Int32VvpWvd = {{(protected )?}}constant [[INT]] {{16|20}}
+// CHECK: @_T016class_resilience28ClassWithMyResilientPropertyC1rAA0eF6StructVvpWvd = {{(protected )?}}constant [[INT]] {{8|16}}
+// CHECK: @_T016class_resilience28ClassWithMyResilientPropertyC5colors5Int32VvpWvd = {{(protected )?}}constant [[INT]] {{12|20}}
-// CHECK: @_T016class_resilience30ClassWithIndirectResilientEnumC1s14resilient_enum10FunnyShapeOvpWvd = {{(protected )?}}constant [[INT]] {{12|16}}
-// CHECK: @_T016class_resilience30ClassWithIndirectResilientEnumC5colors5Int32VvpWvd = {{(protected )?}}constant [[INT]] {{16|24}}
+// CHECK: @_T016class_resilience30ClassWithIndirectResilientEnumC1s14resilient_enum10FunnyShapeOvpWvd = {{(protected )?}}constant [[INT]] {{8|16}}
+// CHECK: @_T016class_resilience30ClassWithIndirectResilientEnumC5colors5Int32VvpWvd = {{(protected )?}}constant [[INT]] {{12|24}}
import resilient_class
import resilient_struct
diff --git a/test/IRGen/existentials_opaque_boxed.sil b/test/IRGen/existentials_opaque_boxed.sil
index 02c153a..2a57c9f 100644
--- a/test/IRGen/existentials_opaque_boxed.sil
+++ b/test/IRGen/existentials_opaque_boxed.sil
@@ -80,7 +80,7 @@
// CHECK: [[CONTAINER:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP
// CHECK: [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
// CHECK: [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
-// CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), {{(i64|i32)}} 48, {{(i64|i32)}} 7)
+// CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), {{(i64 48|i32 40)}}, {{(i64|i32)}} 7)
// CHECK: [[BOX_ADDR:%.*]] = bitcast %swift.refcounted* [[BOX]] to <{ %swift.refcounted{{(, \[4 x i8\])?}}, [32 x i8] }>*
// CHECK: [[VALUE_ADDR:%.*]] = getelementptr inbounds <{ %swift.refcounted{{(, \[4 x i8\])?}}, [32 x i8] }>, <{ %swift.refcounted{{(, \[4 x i8\])?}}, [32 x i8] }>* [[BOX_ADDR]], i32 0, i32 {{(1|2)}}
// CHECK: [[INIT_EXIST_ADDR:%.*]] = bitcast [32 x i8]* [[VALUE_ADDR]] to %T25existentials_opaque_boxed14NotInlineFixedV*
@@ -136,7 +136,7 @@
// CHECK: [[VW2:%.*]] = load i8*, i8** [[VW_ADDR2]]
// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[VW2]] to {{(i64|i32)}}
// CHECK: [[ALIGNMASK:%.*]] = and {{(i64|i32)}} [[FLAGS]], 65535
-// CHECK: [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64|i32)}} {{(16|12)}}, [[ALIGNMASK]]
+// CHECK: [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64 16|i32 8)}}, [[ALIGNMASK]]
// CHECK: [[NOTALIGNMASK:%.*]] = xor {{(i64|i32)}} [[ALIGNMASK]], -1
// CHECK: [[ALIGNEDSTART:%.*]] = and {{(i64|i32)}} [[HEADERSIZEPLUSALIGN]], [[NOTALIGNMASK]]
// CHECK: [[HEAPSIZE:%.*]] = add {{(i64|i32)}} [[ALIGNEDSTART]], [[SIZE]]
@@ -179,7 +179,7 @@
// CHECK: [[REFADDR:%.*]] = bitcast [{{(24|12)}} x i8]* %0 to %swift.refcounted**
// CHECK: [[REF:%.*]] = load %swift.refcounted*, %swift.refcounted** [[REFADDR]]
// CHECK: [[ALIGNMASK:%.*]] = and {{(i64|i32)}} [[FLAGS]], 65535
-// CHECK: [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64|i32)}} {{(16|12)}}, [[ALIGNMASK]]
+// CHECK: [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64 16|i32 8)}}, [[ALIGNMASK]]
// CHECK: [[NOTALIGNMASK:%.*]] = xor {{(i64|i32)}} [[ALIGNMASK]], -1
// CHECK: [[ALIGNEDSTART:%.*]] = and {{(i64|i32)}} [[HEADERSIZEPLUSALIGN]], [[NOTALIGNMASK]]
// CHECK: [[HEAPOBJ:%.*]] = bitcast %swift.refcounted* %9 to i8*
@@ -519,8 +519,8 @@
// CHECK: [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
// CHECK: [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
// CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata.3, i32 0, i32 2), {{(i64|i32)}} 64, {{(i64|i32)}} 31)
-// CHECK: [[BOX_ADDR:%.*]] = bitcast %swift.refcounted* [[BOX]] to <{ %swift.refcounted, [{{(20|16)}} x i8], [32 x i8] }>*
-// CHECK: [[VALUE_ADDR:%.*]] = getelementptr inbounds <{ %swift.refcounted, [{{(20|16)}} x i8], [32 x i8] }>, <{ %swift.refcounted, [{{(20|16)}} x i8], [32 x i8] }>* [[BOX_ADDR]], i32 0, i32 {{(1|2)}}
+// CHECK: [[BOX_ADDR:%.*]] = bitcast %swift.refcounted* [[BOX]] to <{ %swift.refcounted, [{{(16|24)}} x i8], [32 x i8] }>*
+// CHECK: [[VALUE_ADDR:%.*]] = getelementptr inbounds <{ %swift.refcounted, [{{(16|24)}} x i8], [32 x i8] }>, <{ %swift.refcounted, [{{(16|24)}} x i8], [32 x i8] }>* [[BOX_ADDR]], i32 0, i32 {{(1|2)}}
// CHECK: [[INIT_EXIST_ADDR:%.*]] = bitcast [32 x i8]* [[VALUE_ADDR]] to %T25existentials_opaque_boxed14FixedOveralignV*
// CHECK: [[INLINEBUFFER_ADDR:%.*]] = bitcast [{{(24|12)}} x i8]* [[INLINEBUFFER]] to %swift.refcounted**
// CHECK: store %swift.refcounted* [[BOX]], %swift.refcounted** [[INLINEBUFFER_ADDR]]
diff --git a/test/IRGen/keypaths.sil b/test/IRGen/keypaths.sil
index 8e5d64e..56f038f 100644
--- a/test/IRGen/keypaths.sil
+++ b/test/IRGen/keypaths.sil
@@ -75,7 +75,7 @@
// CHECK-SAME: <i32 0x8000_0004>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- 0x4000_0000 (class) + offset of C.x
-// CHECK-32-SAME: <i32 0x4000_000c> }>
+// CHECK-32-SAME: <i32 0x4000_0008> }>
// CHECK-64-SAME: <i32 0x4000_0010> }>
// -- %e: C.y
@@ -87,7 +87,7 @@
// CHECK-SAME: <i32 0x8000_0004>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- 0x4000_0000 (class) + offset of C.y
-// CHECK-32-SAME: <i32 0x4000_0010> }>
+// CHECK-32-SAME: <i32 0x4000_000c> }>
// CHECK-64-SAME: <i32 0x4000_0018> }>
// -- %f: C.z
@@ -99,7 +99,7 @@
// CHECK-SAME: <i32 0x8000_0004>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- 0x4000_0000 (class) + offset of C.z
-// CHECK-32-SAME: <i32 0x4000_001c> }>
+// CHECK-32-SAME: <i32 0x4000_0018> }>
// CHECK-64-SAME: <i32 0x4000_0030> }>
// -- %g: S.z.x
@@ -118,7 +118,7 @@
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// CHECK: %swift.type* (i8*)*
// -- 0x4000_0000 (class) + offset of C.x
-// CHECK-32-SAME: <i32 0x4000_000c> }>
+// CHECK-32-SAME: <i32 0x4000_0008> }>
// CHECK-64-SAME: <i32 0x4000_0010> }>
// -- %h: C.z.x
@@ -132,7 +132,7 @@
// CHECK-64-SAME: <i32 0x8000_0014>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- 0x4000_0000 (class) + offset of C.z
-// CHECK-32-SAME: <i32 0x4000_001c>,
+// CHECK-32-SAME: <i32 0x4000_0018>,
// CHECK-64-SAME: <i32 0x4000_0030>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// CHECK: %swift.type* (i8*)*
diff --git a/test/IRGen/literals.sil b/test/IRGen/literals.sil
index ce5987b..b45a16b 100644
--- a/test/IRGen/literals.sil
+++ b/test/IRGen/literals.sil
@@ -7,11 +7,11 @@
// CHECK: [[U16_0:@.*]] = private unnamed_addr constant [8 x i16] [i16 104, i16 101, i16 108, i16 112, i16 9, i16 109, i16 101, i16 0]
// CHECK: [[U16_1:@.*]] = private unnamed_addr constant [4 x i16] [i16 0, i16 120, i16 427, i16 0]
// CHECK: @_T0s19_UTF16StringStorageCN = external global %objc_class
-// CHECK: [[UTF16_CSTR_0:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, i8, [8 x i16] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s19_UTF16StringStorageCN to %swift.type*), i32 4, i32 0 }, i32 7, i32 8, i8 0, i8 0, [8 x i16] [i16 104, i16 101, i16 108, i16 112, i16 9, i16 109, i16 101, i16 0] }
-// CHECK: [[UTF16_CSTR_1:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, i8, [9 x i16] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s19_UTF16StringStorageCN to %swift.type*), i32 4, i32 0 }, i32 8, i32 9, i8 0, i8 0, [9 x i16] [i16 104, i16 101, i16 108, i16 112, i16 9, i16 109, i16 101, i16 0, i16 0] }
+// CHECK: [[UTF16_CSTR_0:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, i8, [8 x i16] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s19_UTF16StringStorageCN to %swift.type*), i64 8589934594 }, i32 7, i32 8, i8 0, i8 0, [8 x i16] [i16 104, i16 101, i16 108, i16 112, i16 9, i16 109, i16 101, i16 0] }
+// CHECK: [[UTF16_CSTR_1:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, i8, [9 x i16] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s19_UTF16StringStorageCN to %swift.type*), i64 8589934594 }, i32 8, i32 9, i8 0, i8 0, [9 x i16] [i16 104, i16 101, i16 108, i16 112, i16 9, i16 109, i16 101, i16 0, i16 0] }
// CHECK: @_T0s20_Latin1StringStorageCN = external global %objc_class
-// CHECK: [[CSTR_0:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, [12 x i8] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s20_Latin1StringStorageCN to %swift.type*), i32 4, i32 0 }, i32 11, i32 12, i8 0, [12 x i8] c"help\09me too\00" }
-// CHECK: [[CSTR_1:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, [13 x i8] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s20_Latin1StringStorageCN to %swift.type*), i32 4, i32 0 }, i32 12, i32 13, i8 0, [13 x i8] c"help\09me too\00\00" }
+// CHECK: [[CSTR_0:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, [12 x i8] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s20_Latin1StringStorageCN to %swift.type*), i64 8589934594 }, i32 11, i32 12, i8 0, [12 x i8] c"help\09me too\00" }
+// CHECK: [[CSTR_1:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, [13 x i8] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s20_Latin1StringStorageCN to %swift.type*), i64 8589934594 }, i32 12, i32 13, i8 0, [13 x i8] c"help\09me too\00\00" }
sil_stage canonical
diff --git a/test/IRGen/objc_class_empty_fields.swift b/test/IRGen/objc_class_empty_fields.swift
index 5a3e204..dfdb5fd 100644
--- a/test/IRGen/objc_class_empty_fields.swift
+++ b/test/IRGen/objc_class_empty_fields.swift
@@ -5,7 +5,7 @@
// SR-1055
// CHECK-64: @_DATA__TtC23objc_class_empty_fields14OneEnumWrapper = private constant { {{.*}}* } { i32 {{[0-9]+}}, i32 16, i32 24
-// CHECK-32: @_DATA__TtC23objc_class_empty_fields14OneEnumWrapper = private constant { {{.*}}* } { i32 {{[0-9]+}}, i32 12, i32 16
+// CHECK-32: @_DATA__TtC23objc_class_empty_fields14OneEnumWrapper = private constant { {{.*}}* } { i32 {{[0-9]+}}, i32 8, i32 12
enum OneCaseEnum {
case X
diff --git a/test/IRGen/typed_boxes.sil b/test/IRGen/typed_boxes.sil
index 8999242..502d614 100644
--- a/test/IRGen/typed_boxes.sil
+++ b/test/IRGen/typed_boxes.sil
@@ -7,15 +7,13 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc void @pod_box_8_8_a
sil @pod_box_8_8_a : $@convention(thin) () -> () {
entry:
- // CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[POD_8_8_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD:i[0-9]+]] 24, [[WORD]] 7)
+ // CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[POD_8_8_METADATA:@metadata[0-9.]*]], i32 0, i32 2), [[WORD:i[0-9]+]] [[POD_8_8_SIZE:[0-9]+]], [[WORD]] 7)
%a = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.Int64>
- // CHECK-32: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[4 x i8\], \[8 x i8\] \}>]]*
- // CHECK-32: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 2
- // CHECK-64: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
- // CHECK-64: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
+ // CHECK: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
+ // CHECK: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
// CHECK: [[BOX_DATA_1:%.*]] = bitcast [8 x i8]* [[BOX_DATA]] to i64*
%b = project_box %a : $<τ_0_0> { var τ_0_0 } <Builtin.Int64>, 0
- // CHECK: call void @swift_rt_swift_deallocUninitializedObject(%swift.refcounted* [[BOX]], [[WORD]] 24, [[WORD]] 7)
+ // CHECK: call void @swift_rt_swift_deallocUninitializedObject(%swift.refcounted* [[BOX]], [[WORD]] [[POD_8_8_SIZE]], [[WORD]] 7)
dealloc_box %a : $<τ_0_0> { var τ_0_0 } <Builtin.Int64>
return undef : $()
}
@@ -23,15 +21,13 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc void @pod_box_8_8_b
sil @pod_box_8_8_b : $@convention(thin) () -> () {
entry:
- // CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[POD_8_8_METADATA]], {{.*}} [[WORD]] 24, [[WORD]] 7)
+ // CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[POD_8_8_METADATA]], i32 0, i32 2), [[WORD]] [[POD_8_8_SIZE]], [[WORD]] 7)
%a = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.FPIEEE64>
- // CHECK-32: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[4 x i8\], \[8 x i8\] \}>]]*
- // CHECK-32: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 2
- // CHECK-64: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
- // CHECK-64: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
+ // CHECK: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
+ // CHECK: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
// CHECK: [[BOX_DATA_1:%.*]] = bitcast [8 x i8]* [[BOX_DATA]] to double*
%b = project_box %a : $<τ_0_0> { var τ_0_0 } <Builtin.FPIEEE64>, 0
- // CHECK: call void @swift_rt_swift_deallocUninitializedObject(%swift.refcounted* [[BOX]], [[WORD]] 24, [[WORD]] 7)
+ // CHECK: call void @swift_rt_swift_deallocUninitializedObject(%swift.refcounted* [[BOX]], [[WORD]] [[POD_8_8_SIZE]], [[WORD]] 7)
dealloc_box %a : $<τ_0_0> { var τ_0_0 } <Builtin.FPIEEE64>
return undef : $()
}
@@ -46,7 +42,7 @@
entry:
// CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[POD_32_32_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 64, [[WORD]] 31)
%a = alloc_box $<τ_0_0> { var τ_0_0 } <OverAligned>
- // CHECK-32: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_32_32_LAYOUT:<\{ %swift.refcounted, \[20 x i8\], \[32 x i8\] \}>]]*
+ // CHECK-32: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_32_32_LAYOUT:<\{ %swift.refcounted, \[24 x i8\], \[32 x i8\] \}>]]*
// CHECK-64: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_32_32_LAYOUT:<\{ %swift.refcounted, \[16 x i8\], \[32 x i8\] \}>]]*
// CHECK: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_32_32_LAYOUT]], [[POD_32_32_LAYOUT]]* [[BOX_RAW]], i32 0, i32 2
// CHECK: [[BOX_DATA_1:%.*]] = bitcast [32 x i8]* [[BOX_DATA]] to %T11typed_boxes11OverAlignedV*
@@ -65,7 +61,7 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc void @rc_box_a
sil @rc_box_a : $@convention(thin) () -> () {
entry:
- // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 16, [[WORD]] 3)
+ // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 12, [[WORD]] 3)
// CHECK-64: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 24, [[WORD]] 7)
%a = alloc_box $<τ_0_0> { var τ_0_0 } <C>
// CHECK: bitcast %swift.refcounted** {{%.*}} to %T11typed_boxes1CC**
@@ -78,7 +74,7 @@
sil @rc_box_b : $@convention(thin) () -> () {
entry:
// TODO: Should reuse metadata
- // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA]], {{.*}} [[WORD]] 16, [[WORD]] 3)
+ // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA]], {{.*}} [[WORD]] 12, [[WORD]] 3)
// CHECK-64: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA]], {{.*}} [[WORD]] 24, [[WORD]] 7)
%a = alloc_box $<τ_0_0> { var τ_0_0 } <D>
// CHECK: bitcast %swift.refcounted** {{%.*}} to %T11typed_boxes1DC**
@@ -90,7 +86,7 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc void @unknown_rc_box
sil @unknown_rc_box : $@convention(thin) () -> () {
entry:
- // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[UNKNOWN_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 16, [[WORD]] 3)
+ // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[UNKNOWN_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 12, [[WORD]] 3)
// CHECK-64: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[UNKNOWN_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 24, [[WORD]] 7)
%a = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.UnknownObject>
%b = project_box %a : $<τ_0_0> { var τ_0_0 } <Builtin.UnknownObject>, 0
@@ -158,10 +154,8 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc i64 @proj_box
sil @proj_box : $@convention(thin) (<τ_0_0> { var τ_0_0 } <Builtin.Int64>) -> Builtin.Int64 {
entry(%0 : $<τ_0_0> { var τ_0_0 } <Builtin.Int64>):
- // CHECK-32: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* %0 to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[4 x i8\], \[8 x i8\] \}>]]*
- // CHECK-32: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 2
- // CHECK-64: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* %0 to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
- // CHECK-64: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
+ // CHECK: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* %0 to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
+ // CHECK: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
// CHECK: [[BOX_DATA_1:%.*]] = bitcast [8 x i8]* [[BOX_DATA]] to i64*
%p = project_box %0 : $<τ_0_0> { var τ_0_0 } <Builtin.Int64>, 0
// CHECK: [[R:%.*]] = load i64, i64* [[BOX_DATA_1]]
diff --git a/test/IRGen/vector_reduction.swift b/test/IRGen/vector_reduction.swift
index aa93041..8ebc383 100644
--- a/test/IRGen/vector_reduction.swift
+++ b/test/IRGen/vector_reduction.swift
@@ -7,7 +7,7 @@
// We were missing target transform info and not vectorizing the loop below.
-// CHECK: xor <2 x i64>
+// CHECK: xor <{{(2|4|8)}} x i64>
public func f(a: UnsafePointer<Int>, b: UnsafePointer<Int>, count: Int) -> Int {
var c = 0
diff --git a/test/SIL/Parser/coroutines.sil b/test/SIL/Parser/coroutines.sil
new file mode 100644
index 0000000..2841c71
--- /dev/null
+++ b/test/SIL/Parser/coroutines.sil
@@ -0,0 +1,47 @@
+// RUN: %target-swift-frontend %s -emit-silgen -verify
+
+sil_stage raw
+
+import Swift
+
+sil @once_signature : $@yield_once () -> (@yields Int, @yields Float) {
+bb0:
+ %0 = tuple ()
+ return %0 : $()
+}
+
+sil @many_signature : $@yield_many () -> (@yields Int, @yields Float) {
+bb0:
+ %0 = tuple ()
+ return %0 : $()
+}
+
+sil @yield : $@yield_once (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+ yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb2
+
+bb1:
+ %r = tuple ()
+ return %r : $()
+
+bb2:
+ unwind
+}
+
+sil @yield_many : $@yield_many (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+ yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb3
+
+bb1:
+ yield (%0 : $Int, %1 : $Float), resume bb2, unwind bb4
+
+bb2:
+ %r = tuple ()
+ return %r : $()
+
+bb3:
+ unwind
+
+bb4:
+ unwind
+}
diff --git a/test/SIL/Parser/coroutines_failure_merge.sil b/test/SIL/Parser/coroutines_failure_merge.sil
new file mode 100644
index 0000000..bf791ee
--- /dev/null
+++ b/test/SIL/Parser/coroutines_failure_merge.sil
@@ -0,0 +1,20 @@
+// RUN: not --crash %target-swift-frontend %s -emit-silgen -verify
+
+sil_stage raw
+
+import Swift
+
+sil @yield : $@yield_many (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+ yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb2
+
+bb1:
+ br bb3
+
+bb2:
+ br bb3
+
+bb3:
+ unreachable
+}
+
diff --git a/test/SIL/Parser/coroutines_failure_unwind_return.sil b/test/SIL/Parser/coroutines_failure_unwind_return.sil
new file mode 100644
index 0000000..4f66823
--- /dev/null
+++ b/test/SIL/Parser/coroutines_failure_unwind_return.sil
@@ -0,0 +1,18 @@
+// RUN: not --crash %target-swift-frontend %s -emit-silgen -verify
+
+sil_stage raw
+
+import Swift
+
+sil @yield : $@yield_once (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+ yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb2
+
+bb1:
+ %r = tuple ()
+ return %r : $()
+
+bb2:
+ %r2 = tuple ()
+ return %r2 : $()
+}
diff --git a/test/SIL/Parser/coroutines_failure_unwind_reuse.sil b/test/SIL/Parser/coroutines_failure_unwind_reuse.sil
new file mode 100644
index 0000000..39c6dfb
--- /dev/null
+++ b/test/SIL/Parser/coroutines_failure_unwind_reuse.sil
@@ -0,0 +1,24 @@
+// RUN: not --crash %target-swift-frontend %s -emit-silgen -verify
+
+sil_stage raw
+
+import Swift
+
+sil @yield : $@yield_many (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+ yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb3
+
+bb1:
+ yield (%0 : $Int, %1 : $Float), resume bb2, unwind bb3
+
+bb2:
+ %r = tuple ()
+ return %r : $()
+
+bb3:
+ unwind
+
+bb4:
+ unwind
+}
+
diff --git a/test/SIL/Parser/coroutines_failure_yieldonce_return.sil b/test/SIL/Parser/coroutines_failure_yieldonce_return.sil
new file mode 100644
index 0000000..05de652
--- /dev/null
+++ b/test/SIL/Parser/coroutines_failure_yieldonce_return.sil
@@ -0,0 +1,11 @@
+// RUN: not --crash %target-swift-frontend %s -emit-silgen -verify
+
+sil_stage canonical
+
+import Swift
+
+sil @once_signature : $@yield_once () -> (@yields Int, @yields Float) {
+bb0:
+ %0 = tuple ()
+ return %0 : $()
+}
diff --git a/test/SIL/Parser/coroutines_failure_yieldonce_twice.sil b/test/SIL/Parser/coroutines_failure_yieldonce_twice.sil
new file mode 100644
index 0000000..382169d
--- /dev/null
+++ b/test/SIL/Parser/coroutines_failure_yieldonce_twice.sil
@@ -0,0 +1,24 @@
+// RUN: not --crash %target-swift-frontend %s -emit-silgen -verify
+
+sil_stage canonical
+
+import Swift
+
+sil @yield : $@yield_once (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+ yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb3
+
+bb1:
+ yield (%0 : $Int, %1 : $Float), resume bb2, unwind bb4
+
+bb2:
+ %r = tuple ()
+ return %r : $()
+
+bb3:
+ unwind
+
+bb4:
+ unwind
+}
+
diff --git a/test/SILGen/transparent_attribute.swift b/test/SILGen/transparent_attribute.swift
index 8174a77..f0a72fd 100644
--- a/test/SILGen/transparent_attribute.swift
+++ b/test/SILGen/transparent_attribute.swift
@@ -1,212 +1,14 @@
// RUN: %target-swift-frontend -emit-silgen -emit-verbose-sil -enable-sil-ownership %s | %FileCheck %s
// Test that the attribute gets set on default argument generators.
+
+// CHECK-LABEL: sil hidden [transparent] @_T021transparent_attribute0A23FuncWithDefaultArgumentS2i1x_tFfA_ : $@convention(thin) () -> Int {
+
+// CHECK-LABEL: sil hidden [transparent] @_T021transparent_attribute0A23FuncWithDefaultArgumentS2i1x_tF : $@convention(thin) (Int) -> Int {
+
@_transparent func transparentFuncWithDefaultArgument (x: Int = 1) -> Int {
return x
}
func useTransparentFuncWithDefaultArgument() -> Int {
- return transparentFuncWithDefaultArgument();
-
- // CHECK-LABEL: sil hidden @_T021transparent_attribute37useTransparentFuncWithDefaultArgumentSiyF
- // CHECK: apply {{.*}} line:8:44
- // CHECK: apply {{.*}} line:8:10
- // CHECK: return
-
-}
-
-func transparentFuncWithoutDefaultArgument (x: Int = 1) -> Int {
- return x
-}
-func useTransparentFuncWithoutDefaultArgument() -> Int {
- return transparentFuncWithoutDefaultArgument();
-
- // CHECK-LABEL: sil hidden @_T021transparent_attribute40useTransparentFuncWithoutDefaultArgumentSiyF
- // CHECK: apply {{.*}} line:21:47
- // CHECK-NOT: transparent
- // CHECK: apply {{.*}} line:21:10
- // CHECK: return
-
-}
-
-// Make sure the transparent attribute is set on constructors (allocating and initializing).
-struct StructWithTranspConstructor {
- @_transparent init () {}
-}
-func testStructWithTranspConstructor() -> StructWithTranspConstructor {
- return StructWithTranspConstructor()
-
- // transparent_attribute.StructWithTranspConstructor.constructor
- // CHECK-APPLY: sil hidden @_T021transparent_attribute27StructWithTranspConstructorV{{[_0-9a-zA-Z]*}}fC
-
- // testStructWithTranspConstructor
- // CHECK-APPLY: _T21transparent_attribute31testStructWithTranspConstructorFT_VS_27StructWithTranspConstructor
- // CHECK: apply {{.*}} line:36:10
-
-}
-
-struct MySt {}
-var _x = MySt()
-var x1 : MySt {
- @_transparent
- get {
- return _x
- }
- @_transparent
- set {
- _x = newValue
- }
-}
-var x2 : MySt {
- @_transparent
- set(v) {
- _x = v
- }
- @_transparent
- get {
- return _x
- }
-}
-func testProperty(z: MySt) {
- x1 = z
- x2 = z
- var m1 : MySt = x1
- var m2 : MySt = x2
- // CHECK-APPLY: sil hidden @_T021transparent_attribute12testPropertyyAA4MyStV1z_tF
- // CHECK: function_ref @_T021transparent_attribute2x1AA4MyStVvs
- // CHECK-NEXT: apply
- // CHECK: function_ref @_T021transparent_attribute2x2AA4MyStVvs
- // CHECK-NEXT: apply
- // CHECK: function_ref @_T021transparent_attribute2x1AA4MyStVvg
- // CHECK-NEXT: apply
- // CHECK: function_ref @_T021transparent_attribute2x2AA4MyStVvg
- // CHECK-NEXT: apply
-}
-
-var _tr2 = MySt()
-var _tr3 = MySt()
-struct MyTranspStruct {}
-extension MyTranspStruct {
- @_transparent
- init(input : MySt) {}
- mutating
- func tr1() {}
- var tr2: MySt {
- get {
- return _tr2
- }
- set {
- _tr2 = newValue
- }
- }
-}
-
-extension MyTranspStruct {
- @_transparent
- var tr3: MySt {
- get {
- return _tr3
- }
- set {
- _tr3 = newValue
- }
- }
-}
-
-func testStructExtension() {
- var c : MyTranspStruct = MyTranspStruct(input: _x)
- c.tr1()
- var s : MySt = c.tr2
- var t : MySt = c.tr3
- // CHECK-APPLY: sil hidden @_TF21transparent_attribute13testStructExtensionFT_T_
- // CHECK: [[INIT:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV{{[_0-9a-zA-Z]*}}fC
- // CHECK: apply [[INIT]]
- // CHECK: [[TR1:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV3tr1{{[_0-9a-zA-Z]*}}F
- // CHECK: apply [[TR1]]
- // CHECK: [[TR2:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV3tr2AA0C2StVvg
- // CHECK: apply [[TR2]]
- // CHECK: [[TR3:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV3tr3AA0C2StVvg
- // CHECK: apply [[TR3]]
-}
-
-enum MyEnum {
- case onetransp
- case twotransp
-}
-
-extension MyEnum {
- @_transparent
- func tr3() {}
-}
-
-func testEnumExtension() {
- MyEnum.onetransp.tr3()
- // CHECK-APPLY: sil hidden @_T021transparent_attribute17testEnumExtensionyyF
- // CHECK: [[TR3:%[0-9]+]] = function_ref @_T021transparent_attribute6MyEnumO3tr3{{[_0-9a-zA-Z]*}}F
- // CHECK: [[INIT:%[0-9]+]] = enum $MyEnum, #MyEnum.onetransp!enumelt
- // CHECK: apply [[TR3]]([[INIT]])
-}
-
-struct testVarDecl {
- @_transparent var max: Int {
- get {
- return 0xFF
- }
- mutating
- set {
- max = 0xFF
- }
- }
- func testVarDeclFoo () {
- var z: Int = max
- // CHECK-APPLY: sil hidden @_T021transparent_attribute11testVarDeclV0cdE3Foo{{[_0-9a-zA-Z]*}}F
- // CHECK: [[TR4:%[0-9]+]] = function_ref @_T021transparent_attribute11testVarDeclV3maxSivg
- // CHECK: apply [[TR4]]
- }
-}
-
-struct testVarDeclShortenedSyntax {
- @_transparent static var max: Int { return 0xFF };
- func testVarDeclShortenedSyntaxfoo () {
- var z: Int = testVarDeclShortenedSyntax.max
- // CHECK-APPLY: sil hidden @_T021transparent_attribute26testVarDeclShortenedSyntaxV0cdeF9Syntaxfoo{{[_0-9a-zA-Z]*}}F
- // CHECK: [[TR5:%[0-9]+]] = function_ref @_T021transparent_attribute26testVarDeclShortenedSyntaxV3maxSivgZ
- // CHECK: apply [[TR5]]
- }
-};
-
-@_transparent var transparentOnGlobalVar: Int {
- get {
- return 0xFF
- }
-}
-// CHECK: sil hidden [transparent] @_T021transparent_attribute0A11OnGlobalVarSivg
-
-// Local functions in transparent context are fragile.
-@_transparent public func foo() {
- // CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyF3barL_yyF : $@convention(thin) () -> ()
- func bar() {}
- bar()
-
- // CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyFyycfU_ : $@convention(thin) () -> () {
- let f: () -> () = {}
- f()
-
- // CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyF3zimL_yyF : $@convention(thin) () -> () {
- func zim() {
- // CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyF3zimL_yyF4zangL_yyF : $@convention(thin) () -> () {
- func zang() {
- }
- zang()
- }
- zim()
-}
-
-
-// Check that @_versioned entities have public linkage.
-// CHECK-LABEL: sil @_T021transparent_attribute25referencedFromTransparentyyF : $@convention(thin) () -> () {
-@_versioned func referencedFromTransparent() {}
-
-// CHECK-LABEL: sil [transparent] [serialized] @_T021transparent_attribute23referencesVersionedFuncyycyF : $@convention(thin) () -> @owned @callee_owned () -> () {
-@_transparent public func referencesVersionedFunc() -> () -> () {
- return referencedFromTransparent
+ return transparentFuncWithDefaultArgument()
}
diff --git a/test/SILGen/versioned_attribute.swift b/test/SILGen/versioned_attribute.swift
index 5a01525..b544b48 100644
--- a/test/SILGen/versioned_attribute.swift
+++ b/test/SILGen/versioned_attribute.swift
@@ -1,5 +1,14 @@
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -emit-verbose-sil %s | %FileCheck %s
+// Check that @_versioned entities have public linkage.
+// CHECK-LABEL: sil @_T019versioned_attribute25referencedFromTransparentyyF : $@convention(thin) () -> () {
+@_versioned func referencedFromTransparent() {}
+
+// CHECK-LABEL: sil [serialized] @_T019versioned_attribute23referencesVersionedFuncyycyF : $@convention(thin) () -> @owned @callee_owned () -> () {
+@_inlineable public func referencesVersionedFunc() -> () -> () {
+ return referencedFromTransparent
+}
+
@_versioned class Horse {
var mouth: AnyObject?
}
diff --git a/test/Sema/diag_erroneous_iuo.swift b/test/Sema/diag_erroneous_iuo.swift
index 2e51057..d938be6 100644
--- a/test/Sema/diag_erroneous_iuo.swift
+++ b/test/Sema/diag_erroneous_iuo.swift
@@ -81,6 +81,8 @@
var x: V
var y: W
+ var fn1: (Int!) -> Int // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ var fn2: (Int) -> Int! // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
subscript (
index: ImplicitlyUnwrappedOptional<Int> // expected-error {{the spelling 'ImplicitlyUnwrappedOptional' is unsupported; use '!' after the type name}}{{12-40=}}{{43-43=!}}{{43-44=}}
@@ -138,18 +140,53 @@
func vararg(_ first: Int, more: Int!...) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
}
+func varargIdentifier(_ first: Int, more: ImplicitlyUnwrappedOptional<Int>...) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+}
+
func iuoInTuple() -> (Int!) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
return 1
}
-func iuoInTuple2() -> (Float, Int!) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+func iuoInTupleIdentifier() -> (ImplicitlyUnwrappedOptional<Int>) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
return 1
}
+func iuoInTuple2() -> (Float, Int!) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return (1.0, 1)
+}
+
+func iuoInTuple2Identifier() -> (Float, ImplicitlyUnwrappedOptional<Int>) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return (1.0, 1)
+}
+
func takesFunc(_ fn: (Int!) -> Int) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
return fn(0)
}
+func takesFuncIdentifier(_ fn: (ImplicitlyUnwrappedOptional<Int>) -> Int) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return fn(0)
+}
+
+func takesFunc2(_ fn: (Int) -> Int!) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return fn(0)
+}
+
+func takesFunc2Identifier(_ fn: (Int) -> ImplicitlyUnwrappedOptional<Int>) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return fn(0)
+}
+
func returnsFunc() -> (Int!) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
return { $0 }
}
+
+func returnsFuncIdentifier() -> (ImplicitlyUnwrappedOptional<Int>) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return { $0 }
+}
+
+func returnsFunc2() -> (Int) -> Int! { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return { $0 }
+}
+
+func returnsFunc2Identifier() -> (Int) -> ImplicitlyUnwrappedOptional<Int> { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return { $0 }
+}
diff --git a/test/SourceKit/Indexing/index_swift_lib.swift b/test/SourceKit/Indexing/index_swift_lib.swift
deleted file mode 100644
index 16f52a2..0000000
--- a/test/SourceKit/Indexing/index_swift_lib.swift
+++ /dev/null
@@ -1,15 +0,0 @@
-// REQUIRES: FIXME
-
-// RUN: %sourcekitd-test -req=index %swiftlib_dir/macosx/x86_64/Swift.swiftmodule -- %mcp_opt > %t.txt
-// RUN: %FileCheck %s -input-file %t.txt
-
-// CHECK: key.name: "Dictionary",
-// CHECK-NEXT: key.usr: "s:Vs10Dictionary",
-
-// RUN: %FileCheck %s -input-file %t.txt -check-prefix=CHECK-INTERNAL
-// RUN: %sourcekitd-test -req=index %swiftlib_dir/macosx/x86_64/Foundation.swiftmodule -- %clang-importer-sdk %mcp_opt > %t.foundation.txt
-// RUN: %FileCheck %s -input-file %t.foundation.txt -check-prefix=CHECK-FOUNDATION
-
-// CHECK-INTERNAL-NOT: key.name: "_bridgeToObjectiveCUnconditional",
-
-// CHECK-FOUNDATION-NOT: _convertStringToNSString
diff --git a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
index 6c36768..94fd5c1 100644
--- a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
+++ b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
@@ -6,14 +6,26 @@
class C {<UnknownDecl>
func bar(_ a: Int) <CodeBlock>{}</CodeBlock></UnknownDecl><UnknownDecl>
func bar1(_ a: Float) -> Float <CodeBlock>{ <UnknownStmt>return <UnknownExpr><FloatLiteralExpr>-0.6 </FloatLiteralExpr>+ <FloatLiteralExpr>0.1 </FloatLiteralExpr>- <FloatLiteralExpr>0.3 </FloatLiteralExpr></UnknownExpr></UnknownStmt>}</CodeBlock></UnknownDecl><UnknownDecl>
+ func bar2(a: Int, b: Int, c:Int) -> Int <CodeBlock>{ <UnknownStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></UnknownStmt>}</CodeBlock></UnknownDecl><UnknownDecl>
+ func bar3(a: Int) -> Int <CodeBlock>{ <UnknownStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></UnknownStmt>}</CodeBlock></UnknownDecl><UnknownDecl>
+ func bar4(_ a: Int) -> Int <CodeBlock>{ <UnknownStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></UnknownStmt>}</CodeBlock></UnknownDecl><UnknownDecl>
func foo() <CodeBlock>{<UnknownDecl>
var a = /*comment*/<StringLiteralExpr>"abc"/*comment*/</StringLiteralExpr></UnknownDecl><UnknownDecl>
var b = /*comment*/<IntegerLiteralExpr>+2/*comment*/</IntegerLiteralExpr></UnknownDecl><UnknownExpr>
- bar(<IntegerLiteralExpr>1</IntegerLiteralExpr>)</UnknownExpr><UnknownExpr>
- bar(<IntegerLiteralExpr>+10</IntegerLiteralExpr>)</UnknownExpr><UnknownExpr>
- bar(<IntegerLiteralExpr>-10</IntegerLiteralExpr>)</UnknownExpr><UnknownExpr>
- bar1(<FloatLiteralExpr>-1.1</FloatLiteralExpr>)</UnknownExpr><UnknownExpr>
- bar1(<FloatLiteralExpr>1.1</FloatLiteralExpr>)</UnknownExpr><UnknownDecl>
- var f = /*comments*/<FloatLiteralExpr>+0.1/*comments*/</FloatLiteralExpr></UnknownDecl>
+ bar(<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr>
+ bar(<FunctionCallArgument><IntegerLiteralExpr>+10</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr>
+ bar(<FunctionCallArgument><IntegerLiteralExpr>-10</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr>
+ bar1(<FunctionCallArgument><FloatLiteralExpr>-1.1</FloatLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr>
+ bar1(<FunctionCallArgument><FloatLiteralExpr>1.1</FloatLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownDecl>
+ var f = /*comments*/<FloatLiteralExpr>+0.1/*comments*/</FloatLiteralExpr></UnknownDecl><UnknownExpr>
+ foo()</UnknownExpr>
+ }</CodeBlock></UnknownDecl><UnknownDecl>
+
+ func foo1() <CodeBlock>{<UnknownExpr>
+ _ = bar2(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b:<IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c:<IntegerLiteralExpr>2</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr>
+ _ = bar2(<FunctionCallArgument>a:<UnknownExpr><IntegerLiteralExpr>1 </IntegerLiteralExpr>+ <IntegerLiteralExpr>1</IntegerLiteralExpr></UnknownExpr>, </FunctionCallArgument><FunctionCallArgument>b:<UnknownExpr><IntegerLiteralExpr>2 </IntegerLiteralExpr>* <IntegerLiteralExpr>2 </IntegerLiteralExpr>+ <IntegerLiteralExpr>2</IntegerLiteralExpr></UnknownExpr>, </FunctionCallArgument><FunctionCallArgument>c:<UnknownExpr><IntegerLiteralExpr>2 </IntegerLiteralExpr>+ <IntegerLiteralExpr>2</IntegerLiteralExpr></UnknownExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr>
+ _ = bar2(<FunctionCallArgument>a : <UnknownExpr>bar2(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr>, </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr>
+ _ = bar3(<FunctionCallArgument>a : <UnknownExpr>bar3(<FunctionCallArgument>a: <UnknownExpr>bar3(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr></FunctionCallArgument>)</UnknownExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr>
+ _ = bar4(<FunctionCallArgument><UnknownExpr>bar4(<FunctionCallArgument><UnknownExpr>bar4(<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr></FunctionCallArgument>)</UnknownExpr></FunctionCallArgument>)</UnknownExpr>
}</CodeBlock></UnknownDecl>
}</UnknownDecl>
diff --git a/test/Syntax/round_trip_parse_gen.swift b/test/Syntax/round_trip_parse_gen.swift
index 839126a..68bc7ef 100644
--- a/test/Syntax/round_trip_parse_gen.swift
+++ b/test/Syntax/round_trip_parse_gen.swift
@@ -6,6 +6,9 @@
class C {
func bar(_ a: Int) {}
func bar1(_ a: Float) -> Float { return -0.6 + 0.1 - 0.3 }
+ func bar2(a: Int, b: Int, c:Int) -> Int { return 1 }
+ func bar3(a: Int) -> Int { return 1 }
+ func bar4(_ a: Int) -> Int { return 1 }
func foo() {
var a = /*comment*/"abc"/*comment*/
var b = /*comment*/+2/*comment*/
@@ -15,5 +18,14 @@
bar1(-1.1)
bar1(1.1)
var f = /*comments*/+0.1/*comments*/
+ foo()
+ }
+
+ func foo1() {
+ _ = bar2(a:1, b:2, c:2)
+ _ = bar2(a:1 + 1, b:2 * 2 + 2, c:2 + 2)
+ _ = bar2(a : bar2(a: 1, b: 2, c: 3), b: 2, c: 3)
+ _ = bar3(a : bar3(a: bar3(a: 1)))
+ _ = bar4(bar4(bar4(1)))
}
}
diff --git a/test/attr/attr_availability_transitive_ios.swift b/test/attr/attr_availability_transitive_ios.swift
new file mode 100644
index 0000000..8ed79a0
--- /dev/null
+++ b/test/attr/attr_availability_transitive_ios.swift
@@ -0,0 +1,37 @@
+// RUN: %target-typecheck-verify-swift
+// REQUIRES: OS=ios
+
+// Allow referencing unavailable API in situations where the caller is marked unavailable in the same circumstances.
+
+@available(iOS, unavailable)
+func ios() {} // expected-note 2{{'ios()' has been explicitly marked unavailable here}}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension() {}
+
+func call_ios_extension() {
+ ios_extension() // OK; ios_extension is only unavailable if -application-extension is passed.
+}
+func call_ios() {
+ ios() // expected-error {{'ios()' is unavailable}}
+}
+
+@available(iOS, unavailable)
+func ios_call_ios_extension() {
+ ios_extension() // OK; ios_extension is only unavailable if -application-extension is passed.
+}
+
+@available(iOS, unavailable)
+func ios_call_ios() {
+ ios() // OK; same
+}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension_call_ios_extension() {
+ ios_extension()
+}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension_call_ios() {
+ ios() // expected-error {{'ios()' is unavailable}}
+}
diff --git a/test/attr/attr_availability_transitive_ios_extension.swift b/test/attr/attr_availability_transitive_ios_extension.swift
new file mode 100644
index 0000000..6f73286
--- /dev/null
+++ b/test/attr/attr_availability_transitive_ios_extension.swift
@@ -0,0 +1,37 @@
+// RUN: %target-typecheck-verify-swift -application-extension
+// REQUIRES: OS=ios
+
+// Allow referencing unavailable API in situations where the caller is marked unavailable in the same circumstances.
+
+@available(iOS, unavailable)
+func ios() {} // expected-note 2{{'ios()' has been explicitly marked unavailable here}}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension() {} // expected-note 2{{'ios_extension()' has been explicitly marked unavailable here}}
+
+func call_ios_extension() {
+ ios_extension() // expected-error {{'ios_extension()' is unavailable}}
+}
+func call_ios() {
+ ios() // expected-error {{'ios()' is unavailable}}
+}
+
+@available(iOS, unavailable)
+func ios_call_ios_extension() {
+ ios_extension() // expected-error {{'ios_extension()' is unavailable}}
+}
+
+@available(iOS, unavailable)
+func ios_call_ios() {
+ ios()
+}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension_call_ios_extension() {
+ ios_extension()
+}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension_call_ios() {
+ ios() // expected-error {{'ios()' is unavailable}}
+}
diff --git a/test/attr/attr_availability_transitive_multiple.swift b/test/attr/attr_availability_transitive_multiple.swift
new file mode 100644
index 0000000..8ef579d
--- /dev/null
+++ b/test/attr/attr_availability_transitive_multiple.swift
@@ -0,0 +1,18 @@
+// RUN: %target-typecheck-verify-swift
+// REQUIRES: OS=macosx
+
+// Check that only the platform we are compiling for is considered when allowing access to unavailable declarations.
+
+@available(iOS, unavailable)
+@available(OSX, unavailable)
+func unavailable() {} // expected-note {{'unavailable()' has been explicitly marked unavailable here}}
+
+@available(iOS, unavailable)
+func call_with_ios_unavailable() {
+ unavailable() // expected-error {{'unavailable()' is unavailable}}
+}
+
+@available(OSX, unavailable)
+func call_with_osx_unavailable() {
+ unavailable() // OK: same
+}
diff --git a/test/attr/attr_availability_transitive_nested.swift b/test/attr/attr_availability_transitive_nested.swift
new file mode 100644
index 0000000..7d8b474
--- /dev/null
+++ b/test/attr/attr_availability_transitive_nested.swift
@@ -0,0 +1,25 @@
+// RUN: %target-typecheck-verify-swift
+// REQUIRES: OS=macosx
+
+// Make sure that a compatible unavailable wrapping doesn't allow referencing declarations that are completely unavailable.
+
+@available(iOS, unavailable)
+class Outer {
+ @available(*, unavailable)
+ func completelyBadMethod() {} // expected-note {{'completelyBadMethod()' has been explicitly marked unavailable here}}
+}
+
+@available(iOS, unavailable)
+func test(outer: Outer) {
+ outer.completelyBadMethod() // expected-error {{'completelyBadMethod()' is unavailable}}
+}
+
+@available(*, unavailable)
+class Outer2 { // expected-note {{'Outer2' has been explicitly marked unavailable here}}
+ @available(iOS, unavailable)
+ func innerUnavailable() {}
+}
+@available(iOS, unavailable)
+func test2(outer: Outer2) { // expected-error {{'Outer2' is unavailable}}
+ outer.innerUnavailable()
+}
diff --git a/test/attr/attr_availability_transitive_osx.swift b/test/attr/attr_availability_transitive_osx.swift
new file mode 100644
index 0000000..eadaf60
--- /dev/null
+++ b/test/attr/attr_availability_transitive_osx.swift
@@ -0,0 +1,37 @@
+// RUN: %target-typecheck-verify-swift
+// REQUIRES: OS=macosx
+
+// Allow referencing unavailable API in situations where the caller is marked unavailable in the same circumstances.
+
+@available(OSX, unavailable)
+func osx() {} // expected-note 2{{'osx()' has been explicitly marked unavailable here}}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension() {}
+
+func call_osx_extension() {
+ osx_extension() // OK; osx_extension is only unavailable if -application-extension is passed.
+}
+func call_osx() {
+ osx() // expected-error {{'osx()' is unavailable}}
+}
+
+@available(OSX, unavailable)
+func osx_call_osx_extension() {
+ osx_extension() // OK; osx_extension is only unavailable if -application-extension is passed.
+}
+
+@available(OSX, unavailable)
+func osx_call_osx() {
+ osx() // OK; same
+}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension_call_osx_extension() {
+ osx_extension()
+}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension_call_osx() {
+ osx() // expected-error {{'osx()' is unavailable}}
+}
diff --git a/test/attr/attr_availability_transitive_osx_extension.swift b/test/attr/attr_availability_transitive_osx_extension.swift
new file mode 100644
index 0000000..949ef68
--- /dev/null
+++ b/test/attr/attr_availability_transitive_osx_extension.swift
@@ -0,0 +1,37 @@
+// RUN: %target-typecheck-verify-swift -application-extension
+// REQUIRES: OS=macosx
+
+// Allow referencing unavailable API in situations where the caller is marked unavailable in the same circumstances.
+
+@available(OSX, unavailable)
+func osx() {} // expected-note 2{{'osx()' has been explicitly marked unavailable here}}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension() {} // expected-note 2{{'osx_extension()' has been explicitly marked unavailable here}}
+
+func call_osx_extension() {
+ osx_extension() // expected-error {{'osx_extension()' is unavailable}}
+}
+func call_osx() {
+ osx() // expected-error {{'osx()' is unavailable}}
+}
+
+@available(OSX, unavailable)
+func osx_call_osx_extension() {
+ osx_extension() // expected-error {{'osx_extension()' is unavailable}}
+}
+
+@available(OSX, unavailable)
+func osx_call_osx() {
+ osx()
+}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension_call_osx_extension() {
+ osx_extension()
+}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension_call_osx() {
+ osx() // expected-error {{'osx()' is unavailable}}
+}
diff --git a/test/decl/ext/protocol.swift b/test/decl/ext/protocol.swift
index 117a0b5..36af2df 100644
--- a/test/decl/ext/protocol.swift
+++ b/test/decl/ext/protocol.swift
@@ -959,3 +959,43 @@
extension A & B { // okay
}
+
+// Suppress near-miss warning for unlabeled initializers.
+protocol P9 {
+ init(_: Int)
+ init(_: Double)
+}
+
+extension P9 {
+ init(_ i: Int) {
+ self.init(Double(i))
+ }
+}
+
+struct X9 : P9 {
+ init(_: Float) { }
+}
+
+extension X9 {
+ init(_: Double) { }
+}
+
+// Suppress near-miss warning for unlabeled subscripts.
+protocol P10 {
+ subscript (_: Int) -> Int { get }
+ subscript (_: Double) -> Double { get }
+}
+
+extension P10 {
+ subscript(i: Int) -> Int {
+ return Int(self[Double(i)])
+ }
+}
+
+struct X10 : P10 {
+ subscript(f: Float) -> Float { return f }
+}
+
+extension X10 {
+ subscript(d: Double) -> Double { return d }
+}
diff --git a/test/stdlib/KeyPathImplementation.swift b/test/stdlib/KeyPathImplementation.swift
index 8ccde01..8151dc1 100644
--- a/test/stdlib/KeyPathImplementation.swift
+++ b/test/stdlib/KeyPathImplementation.swift
@@ -12,8 +12,7 @@
return (offset + alignMask) & ~alignMask
}
-// FIXME: Object header size will eventually be MemoryLayout<Int>.size * 2
-let classHeaderSize = MemoryLayout<Int>.size + 8
+let classHeaderSize = MemoryLayout<Int>.size * 2
class C<T> {
var x: Int
diff --git a/test/stdlib/StringDiagnostics.swift b/test/stdlib/StringDiagnostics.swift
index 2712ee3..1d36b11 100644
--- a/test/stdlib/StringDiagnostics.swift
+++ b/test/stdlib/StringDiagnostics.swift
@@ -53,6 +53,9 @@
let a10 = nsString <= s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{21-21= as String}}
let a11 = nsString >= s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{21-21= as String}}
let a12 = nsString > s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{21-21= as String}}
+
+ // Shouldn't suggest 'as' in a pattern-matching context, as opposed to all these other situations
+ if case nsString = "" {} // expected-error{{expression pattern of type 'NSString' cannot match values of type 'String'}}
}
func testStringDeprecation(hello: String) {
diff --git a/test/stdlib/TestNSNumberBridging.swift b/test/stdlib/TestNSNumberBridging.swift
index f5c4685..1638226 100644
--- a/test/stdlib/TestNSNumberBridging.swift
+++ b/test/stdlib/TestNSNumberBridging.swift
@@ -658,16 +658,16 @@
let uint = (number!) as? UInt
expectEqual(UInt(exactly: interestingValue), uint)
- // these are disabled because of https://bugs.swift.org/browse/SR-4634
- if uint! != UInt(UInt32.max) && uint! != UInt(UInt32.max - 1) {
- let float = (number!) as? Float
- let expectedFloat = Float(uint!)
- testFloat(expectedFloat, float)
+ let float = (number!) as? Float
+ let expectedFloat = Float(exactly: uint!)
+ if UInt.bitWidth == 32 && uint! >= UInt.max - 1 {
+ expectNil(expectedFloat)
+ } else {
+ testFloat(expectedFloat, float)
}
-
-
+
let double = (number!) as? Double
- let expectedDouble = Double(uint!)
+ let expectedDouble = Double(exactly: uint!)
testDouble(expectedDouble, double)
}
let bridged = interestingValue as NSNumber
diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp
index 5cf9e47..943ae43 100644
--- a/tools/swift-api-digester/swift-api-digester.cpp
+++ b/tools/swift-api-digester/swift-api-digester.cpp
@@ -1282,6 +1282,9 @@
return true;
if (VD->getBaseName().empty())
return true;
+ // This shouldn't happen, being forgiving here.
+ if (!VD->hasAccess())
+ return true;
switch (VD->getFormalAccess()) {
case AccessLevel::Internal:
case AccessLevel::Private:
diff --git a/validation-test/Reflection/functions.swift b/validation-test/Reflection/functions.swift
index 3b4e0b2..8786247 100644
--- a/validation-test/Reflection/functions.swift
+++ b/validation-test/Reflection/functions.swift
@@ -26,8 +26,8 @@
// CHECK-NEXT: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (closure_context size=16 alignment=4 stride=16
-// CHECK-32-NEXT: (field offset=12
+// CHECK-32-NEXT: (closure_context size=12 alignment=4 stride=12
+// CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
@@ -45,8 +45,8 @@
// CHECK-NEXT: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (closure_context size=28 alignment=4 stride=28
-// CHECK-32-NEXT: (field offset=12
+// CHECK-32-NEXT: (closure_context size=24 alignment=4 stride=24
+// CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (opaque_existential size=16 alignment=4 stride=16 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=metadata offset=12
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=4096)))))
@@ -85,8 +85,8 @@
// CHECK-NEXT: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (closure_context size=16 alignment=4 stride=16
-// CHECK-32-NEXT: (field offset=12
+// CHECK-32-NEXT: (closure_context size=12 alignment=4 stride=12
+// CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
@@ -103,12 +103,12 @@
// CHECK-NEXT: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (closure_context size=40 alignment=4 stride=40
+// CHECK-32-NEXT: (closure_context size=36 alignment=4 stride=36
+// CHECK-32-NEXT: (field offset=24
+// CHECK-32-NEXT: (reference kind=strong refcounting=native))
// CHECK-32-NEXT: (field offset=28
// CHECK-32-NEXT: (reference kind=strong refcounting=native))
// CHECK-32-NEXT: (field offset=32
-// CHECK-32-NEXT: (reference kind=strong refcounting=native))
-// CHECK-32-NEXT: (field offset=36
// CHECK-32-NEXT: (reference kind=strong refcounting=native)))
// CHECK-64: Type info:
@@ -132,14 +132,14 @@
// CHECK-NEXT: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (closure_context size=28 alignment=4 stride=28
+// CHECK-32-NEXT: (closure_context size=24 alignment=4 stride=24
+// CHECK-32-NEXT: (field offset=8
+// CHECK-32-NEXT: (reference kind=strong refcounting=native))
// CHECK-32-NEXT: (field offset=12
// CHECK-32-NEXT: (reference kind=strong refcounting=native))
// CHECK-32-NEXT: (field offset=16
// CHECK-32-NEXT: (reference kind=strong refcounting=native))
// CHECK-32-NEXT: (field offset=20
-// CHECK-32-NEXT: (reference kind=strong refcounting=native))
-// CHECK-32-NEXT: (field offset=24
// CHECK-32-NEXT: (reference kind=strong refcounting=native)))
// CHECK-64: Type info:
@@ -171,7 +171,7 @@
// CHECK-32: (class functions.CapturingClass)
// CHECK-32: Type info:
- // CHECK-32: (class_instance size=12 alignment=1 stride=12
+ // CHECK-32: (class_instance size=8 alignment=1 stride=8
@_semantics("optimize.sil.never")
func arity0Capture1() -> () -> () {
let closure = {
@@ -204,8 +204,8 @@
// CHECK-32: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
- // CHECK-32: (closure_context size=32 alignment=8 stride=32
- // CHECK-32-NEXT: (field offset=16
+ // CHECK-32: (closure_context size=24 alignment=8 stride=24
+ // CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (tuple size=16 alignment=8 stride=16 num_extra_inhabitants=0
// CHECK-32-NEXT: (field offset=0
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
@@ -245,8 +245,8 @@
// CHECK-32: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
- // CHECK-32: (closure_context size=20 alignment=4 stride=20
- // CHECK-32-NEXT: (field offset=12
+ // CHECK-32: (closure_context size=16 alignment=4 stride=16
+ // CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (tuple size=8 alignment=4 stride=8 num_extra_inhabitants=0
// CHECK-32-NEXT: (field offset=0
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
@@ -283,8 +283,8 @@
// CHECK-32: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
- // CHECK-32: (closure_context size=16 alignment=4 stride=16
- // CHECK-32-NEXT: (field offset=12
+ // CHECK-32: (closure_context size=12 alignment=4 stride=12
+ // CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (single_payload_enum size=4 alignment=4 stride=4 num_extra_inhabitants=4095
// CHECK-32-NEXT: (field name=some offset=0
// CHECK-32-NEXT: (class_existential size=4 alignment=4 stride=4 num_extra_inhabitants=4096
@@ -326,7 +326,7 @@
// CHECK-32: Type info:
// CHECK-32: (closure_context size=32 alignment=8 stride=32
- // CHECK-32-NEXT: (field offset=12
+ // CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (reference kind=strong refcounting=native))
// CHECK-32-NEXT: (field offset=16
// CHECK-32-NEXT: (tuple size=16 alignment=8 stride=16 num_extra_inhabitants=0
@@ -367,10 +367,10 @@
// CHECK-32: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
- // CHECK-32: (closure_context size=20 alignment=4 stride=20
- // CHECK-32: (field offset=12
+ // CHECK-32: (closure_context size=16 alignment=4 stride=16
+ // CHECK-32: (field offset=8
// CHECK-32: (reference kind=strong refcounting=native))
- // CHECK-32: (field offset=16
+ // CHECK-32: (field offset=12
// CHECK-32: (reference kind=strong refcounting=native)))
@_semantics("optimize.sil.never")
func arity1Capture2() -> (Int) -> () {
@@ -408,7 +408,7 @@
// CHECK-32: Type info:
// CHECK-32: (closure_context size=32 alignment=8 stride=32
- // CHECK-32: (field offset=12
+ // CHECK-32: (field offset=8
// CHECK-32: (reference kind=strong refcounting=native))
// CHECK-32: (field offset=16
// CHECK-32: (tuple size=16 alignment=8 stride=16 num_extra_inhabitants=0
@@ -457,7 +457,7 @@
// CHECK-32: Type info:
// CHECK-32: (closure_context size=32 alignment=8 stride=32
- // CHECK-32: (field offset=12
+ // CHECK-32: (field offset=8
// CHECK-32: (reference kind=strong refcounting=native))
// CHECK-32: (field offset=16
// CHECK-32: (tuple size=16 alignment=8 stride=16 num_extra_inhabitants=0
@@ -510,8 +510,8 @@
// CHECK-32: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32: (closure_context size=16 alignment=4 stride=16
-// CHECK-32-NEXT: (field offset=12
+// CHECK-32: (closure_context size=12 alignment=4 stride=12
+// CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (reference kind=weak refcounting=native)))
reflect(function: C().captureUnownedSelf())
@@ -531,8 +531,8 @@
// CHECK-32: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32: (closure_context size=16 alignment=4 stride=16
-// CHECK-32-NEXT: (field offset=12
+// CHECK-32: (closure_context size=12 alignment=4 stride=12
+// CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (reference kind=unowned refcounting=native)))
doneReflecting()
diff --git a/validation-test/Reflection/functions_objc.swift b/validation-test/Reflection/functions_objc.swift
index dd56664..8e05508 100644
--- a/validation-test/Reflection/functions_objc.swift
+++ b/validation-test/Reflection/functions_objc.swift
@@ -15,16 +15,16 @@
// CHECK-32-NEXT: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (closure_context size=40 alignment=4 stride=40 num_extra_inhabitants=0
-// CHECK-32-NEXT: (field offset=12
+// CHECK-32-NEXT: (closure_context size=36 alignment=4 stride=36 num_extra_inhabitants=0
+// CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field offset=16
+// CHECK-32-NEXT: (field offset=12
// CHECK-32-NEXT: (reference kind=strong refcounting=unknown))
-// CHECK-32-NEXT: (field offset=20
+// CHECK-32-NEXT: (field offset=16
// CHECK-32-NEXT: (builtin size=16 alignment=4 stride=16 num_extra_inhabitants=0))
-// CHECK-32-NEXT: (field offset=36
+// CHECK-32-NEXT: (field offset=32
// CHECK-32-NEXT: (reference kind=strong refcounting=unknown)))
// CHECK-64: Type reference:
diff --git a/validation-test/Reflection/inherits_Swift.swift b/validation-test/Reflection/inherits_Swift.swift
index 67a1c50..7b0aa77 100644
--- a/validation-test/Reflection/inherits_Swift.swift
+++ b/validation-test/Reflection/inherits_Swift.swift
@@ -37,12 +37,12 @@
// CHECK-32: (class inherits_Swift.BaseClass)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (class_instance size=17 alignment=4 stride=20 num_extra_inhabitants=0
-// CHECK-32-NEXT: (field name=w offset=12
+// CHECK-32-NEXT: (class_instance size=13 alignment=4 stride=16 num_extra_inhabitants=0
+// CHECK-32-NEXT: (field name=w offset=8
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=x offset=16
+// CHECK-32-NEXT: (field name=x offset=12
// CHECK-32-NEXT: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254)))))
@@ -73,12 +73,12 @@
// CHECK-32: (class inherits_Swift.DerivedClass)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (class_instance size=24 alignment=4 stride=24 num_extra_inhabitants=0
-// CHECK-32-NEXT: (field name=y offset=17
+// CHECK-32-NEXT: (class_instance size=20 alignment=4 stride=20 num_extra_inhabitants=0
+// CHECK-32-NEXT: (field name=y offset=13
// CHECK-32-NEXT: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254))))
-// CHECK-32-NEXT: (field name=z offset=20
+// CHECK-32-NEXT: (field name=z offset=16
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Array.swift b/validation-test/Reflection/reflect_Array.swift
index c8b84e7..01996e3 100644
--- a/validation-test/Reflection/reflect_Array.swift
+++ b/validation-test/Reflection/reflect_Array.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_Array.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=1
// (unstable implementation details omitted)
diff --git a/validation-test/Reflection/reflect_Bool.swift b/validation-test/Reflection/reflect_Bool.swift
index 9cabb01..7f0fe57 100644
--- a/validation-test/Reflection/reflect_Bool.swift
+++ b/validation-test/Reflection/reflect_Bool.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Bool.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=13 alignment=1 stride=13 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=9 alignment=1 stride=9 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254)))))
diff --git a/validation-test/Reflection/reflect_Character.swift b/validation-test/Reflection/reflect_Character.swift
index d6911ed..cb05d37 100644
--- a/validation-test/Reflection/reflect_Character.swift
+++ b/validation-test/Reflection/reflect_Character.swift
@@ -42,8 +42,8 @@
// CHECK-32: (class reflect_Character.TestClass)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (class_instance size=24 alignment=8 stride=24 num_extra_inhabitants=0
-// CHECK-32-NEXT: (field name=t offset=16
+// CHECK-32-NEXT: (class_instance size=16 alignment=8 stride=16 num_extra_inhabitants=0
+// CHECK-32-NEXT: (field name=t offset=8
// CHECK-32-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_representation offset=0
// CHECK-32-NEXT: (multi_payload_enum size=8 alignment=8 stride=8 num_extra_inhabitants=0
diff --git a/validation-test/Reflection/reflect_Dictionary.swift b/validation-test/Reflection/reflect_Dictionary.swift
index 2eecc2d..5a33cdf 100644
--- a/validation-test/Reflection/reflect_Dictionary.swift
+++ b/validation-test/Reflection/reflect_Dictionary.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_Dictionary.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// (unstable implementation details omitted)
diff --git a/validation-test/Reflection/reflect_Double.swift b/validation-test/Reflection/reflect_Double.swift
index 80904ed..f95deee 100644
--- a/validation-test/Reflection/reflect_Double.swift
+++ b/validation-test/Reflection/reflect_Double.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Double.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=24 alignment=8 stride=24 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=16
+// CHECK-32: (class_instance size=16 alignment=8 stride=16 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Float.swift b/validation-test/Reflection/reflect_Float.swift
index d59b985..fec3513 100644
--- a/validation-test/Reflection/reflect_Float.swift
+++ b/validation-test/Reflection/reflect_Float.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Float.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Int.swift b/validation-test/Reflection/reflect_Int.swift
index a8b8488..056943b 100644
--- a/validation-test/Reflection/reflect_Int.swift
+++ b/validation-test/Reflection/reflect_Int.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Int.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Int16.swift b/validation-test/Reflection/reflect_Int16.swift
index d51a0e1..3818d73 100644
--- a/validation-test/Reflection/reflect_Int16.swift
+++ b/validation-test/Reflection/reflect_Int16.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Int16.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=14 alignment=2 stride=14 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=10 alignment=2 stride=10 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=2 alignment=2 stride=2 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=2 alignment=2 stride=2 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Int32.swift b/validation-test/Reflection/reflect_Int32.swift
index a2d642e..26da3ae 100644
--- a/validation-test/Reflection/reflect_Int32.swift
+++ b/validation-test/Reflection/reflect_Int32.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Int32.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Int64.swift b/validation-test/Reflection/reflect_Int64.swift
index d1a1c1b..9ef651c 100644
--- a/validation-test/Reflection/reflect_Int64.swift
+++ b/validation-test/Reflection/reflect_Int64.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Int64.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=24 alignment=8 stride=24 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=16
+// CHECK-32: (class_instance size=16 alignment=8 stride=16 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Int8.swift b/validation-test/Reflection/reflect_Int8.swift
index b79ff1f..fd8db13 100644
--- a/validation-test/Reflection/reflect_Int8.swift
+++ b/validation-test/Reflection/reflect_Int8.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Int8.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=13 alignment=1 stride=13 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=9 alignment=1 stride=9 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_NSArray.swift b/validation-test/Reflection/reflect_NSArray.swift
index 7abeb2c..f0d735a 100644
--- a/validation-test/Reflection/reflect_NSArray.swift
+++ b/validation-test/Reflection/reflect_NSArray.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_NSArray.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (reference kind=strong refcounting=unknown)))
doneReflecting()
diff --git a/validation-test/Reflection/reflect_NSNumber.swift b/validation-test/Reflection/reflect_NSNumber.swift
index 4f8c3f8..e80fd09 100644
--- a/validation-test/Reflection/reflect_NSNumber.swift
+++ b/validation-test/Reflection/reflect_NSNumber.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_NSNumber.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (reference kind=strong refcounting=unknown)))
doneReflecting()
diff --git a/validation-test/Reflection/reflect_NSSet.swift b/validation-test/Reflection/reflect_NSSet.swift
index f0c1f5c..5704edb 100644
--- a/validation-test/Reflection/reflect_NSSet.swift
+++ b/validation-test/Reflection/reflect_NSSet.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_NSSet.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (reference kind=strong refcounting=unknown)))
doneReflecting()
diff --git a/validation-test/Reflection/reflect_NSString.swift b/validation-test/Reflection/reflect_NSString.swift
index ee02334..ab8fa0c 100644
--- a/validation-test/Reflection/reflect_NSString.swift
+++ b/validation-test/Reflection/reflect_NSString.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_NSString.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (reference kind=strong refcounting=unknown)))
doneReflecting()
diff --git a/validation-test/Reflection/reflect_Set.swift b/validation-test/Reflection/reflect_Set.swift
index dcfb477..267bd21 100644
--- a/validation-test/Reflection/reflect_Set.swift
+++ b/validation-test/Reflection/reflect_Set.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_Set.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// (unstable implementation details omitted)
diff --git a/validation-test/Reflection/reflect_String.swift b/validation-test/Reflection/reflect_String.swift
index 2e8dde6..2941249 100644
--- a/validation-test/Reflection/reflect_String.swift
+++ b/validation-test/Reflection/reflect_String.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_String.TestClass)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (class_instance size=24 alignment=4 stride=24
-// CHECK-32-NEXT: (field name=t offset=12
+// CHECK-32-NEXT: (class_instance size=20 alignment=4 stride=20
+// CHECK-32-NEXT: (field name=t offset=8
// CHECK-32-NEXT: (struct size=12 alignment=4 stride=12 num_extra_inhabitants=0
// (unstable implementation details omitted)
diff --git a/validation-test/Reflection/reflect_UInt.swift b/validation-test/Reflection/reflect_UInt.swift
index 3f951d3..94309fb 100644
--- a/validation-test/Reflection/reflect_UInt.swift
+++ b/validation-test/Reflection/reflect_UInt.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_UInt.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_UInt16.swift b/validation-test/Reflection/reflect_UInt16.swift
index 8d9ee6b..d7ec13b 100644
--- a/validation-test/Reflection/reflect_UInt16.swift
+++ b/validation-test/Reflection/reflect_UInt16.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_UInt16.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=14 alignment=2 stride=14 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=10 alignment=2 stride=10 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=2 alignment=2 stride=2 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=2 alignment=2 stride=2 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_UInt32.swift b/validation-test/Reflection/reflect_UInt32.swift
index 4fd5dcd..5123abd 100644
--- a/validation-test/Reflection/reflect_UInt32.swift
+++ b/validation-test/Reflection/reflect_UInt32.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_UInt32.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_UInt64.swift b/validation-test/Reflection/reflect_UInt64.swift
index 2c8248a..6e672df 100644
--- a/validation-test/Reflection/reflect_UInt64.swift
+++ b/validation-test/Reflection/reflect_UInt64.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_UInt64.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=24 alignment=8 stride=24 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=16
+// CHECK-32: (class_instance size=16 alignment=8 stride=16 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_UInt8.swift b/validation-test/Reflection/reflect_UInt8.swift
index e02710a..4f94618 100644
--- a/validation-test/Reflection/reflect_UInt8.swift
+++ b/validation-test/Reflection/reflect_UInt8.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_UInt8.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=13 alignment=1 stride=13 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=9 alignment=1 stride=9 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_empty_class.swift b/validation-test/Reflection/reflect_empty_class.swift
index 1f337fe..6c54d94 100644
--- a/validation-test/Reflection/reflect_empty_class.swift
+++ b/validation-test/Reflection/reflect_empty_class.swift
@@ -26,7 +26,7 @@
// CHECK-32: (class reflect_empty_class.EmptyClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=12 alignment=1 stride=12 num_extra_inhabitants=0)
+// CHECK-32: (class_instance size=8 alignment=1 stride=8 num_extra_inhabitants=0)
doneReflecting()
diff --git a/validation-test/Reflection/reflect_existential.swift b/validation-test/Reflection/reflect_existential.swift
index 1247dc6..a871580 100644
--- a/validation-test/Reflection/reflect_existential.swift
+++ b/validation-test/Reflection/reflect_existential.swift
@@ -37,8 +37,8 @@
// CHECK-32: (protocol_composition))
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=28 alignment=4 stride=28 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=24 alignment=4 stride=24 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (opaque_existential size=16 alignment=4 stride=16 num_extra_inhabitants=0
// CHECK-32: (field name=metadata offset=12
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=4096)))))
@@ -65,8 +65,8 @@
// CHECK-32: (protocol reflect_existential.P)))
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=32 alignment=4 stride=32 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=28 alignment=4 stride=28 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (opaque_existential size=20 alignment=4 stride=20 num_extra_inhabitants=0
// CHECK-32: (field name=metadata offset=12
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=4096))
@@ -95,8 +95,8 @@
// CHECK-32: (protocol reflect_existential.P)))
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=20 alignment=4 stride=20 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (class_existential size=8 alignment=4 stride=8 num_extra_inhabitants=4096
// CHECK-32: (field name=object offset=0
// CHECK-32: (reference kind=strong refcounting=unknown))
@@ -125,8 +125,8 @@
// CHECK-32: (protocol reflect_existential.CP)))
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=20 alignment=4 stride=20 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (class_existential size=8 alignment=4 stride=8 num_extra_inhabitants=4096
// CHECK-32: (field name=object offset=0
// CHECK-32: (reference kind=strong refcounting=unknown))
@@ -157,8 +157,8 @@
// CHECK-32: (protocol reflect_existential.P)))
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=20 alignment=4 stride=20 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (class_existential size=8 alignment=4 stride=8 num_extra_inhabitants=4096
// CHECK-32: (field name=object offset=0
// CHECK-32: (reference kind=strong refcounting=native))
diff --git a/validation-test/Reflection/reflect_multiple_types.swift b/validation-test/Reflection/reflect_multiple_types.swift
index bdcfba9..c477b22 100644
--- a/validation-test/Reflection/reflect_multiple_types.swift
+++ b/validation-test/Reflection/reflect_multiple_types.swift
@@ -205,15 +205,15 @@
// CHECK-32: (class reflect_multiple_types.TestClass)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (class_instance size=129 alignment=8 stride=136 num_extra_inhabitants=0
-// CHECK-32-NEXT: (field name=t00 offset=12
+// CHECK-32-NEXT: (class_instance size=121 alignment=8 stride=128 num_extra_inhabitants=0
+// CHECK-32-NEXT: (field name=t00 offset=8
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=1
// (unstable implementation details omitted)
-// CHECK-32: (field name=t01 offset=16
+// CHECK-32: (field name=t01 offset=12
// CHECK-32-NEXT: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254))))
-// CHECK-32-NEXT: (field name=t02 offset=24
+// CHECK-32-NEXT: (field name=t02 offset=16
// CHECK-32-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_representation offset=0
// CHECK-32-NEXT: (multi_payload_enum size=8 alignment=8 stride=8 num_extra_inhabitants=0
@@ -223,68 +223,68 @@
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=4096
// CHECK-32-NEXT: (field name=_nativeBuffer offset=0
// CHECK-32-NEXT: (reference kind=strong refcounting=native))))))
-// CHECK-32-NEXT: (field name=t03 offset=32
+// CHECK-32-NEXT: (field name=t03 offset=24
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// (unstable implementation details omitted)
-// CHECK-32: (field name=t04 offset=40
+// CHECK-32: (field name=t04 offset=32
// CHECK-32-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t05 offset=48
+// CHECK-32-NEXT: (field name=t05 offset=40
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t06 offset=52
+// CHECK-32-NEXT: (field name=t06 offset=44
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t07 offset=56
+// CHECK-32-NEXT: (field name=t07 offset=48
// CHECK-32-NEXT: (struct size=2 alignment=2 stride=2 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=2 alignment=2 stride=2 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t08 offset=60
+// CHECK-32-NEXT: (field name=t08 offset=52
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t09 offset=64
+// CHECK-32-NEXT: (field name=t09 offset=56
// CHECK-32-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t10 offset=72
+// CHECK-32-NEXT: (field name=t10 offset=64
// CHECK-32-NEXT: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t11 offset=76
+// CHECK-32-NEXT: (field name=t11 offset=68
// CHECK-32-NEXT: (reference kind=strong refcounting=unknown))
-// CHECK-32-NEXT: (field name=t12 offset=80
+// CHECK-32-NEXT: (field name=t12 offset=72
// CHECK-32-NEXT: (reference kind=strong refcounting=unknown))
-// CHECK-32-NEXT: (field name=t13 offset=84
+// CHECK-32-NEXT: (field name=t13 offset=76
// CHECK-32-NEXT: (reference kind=strong refcounting=unknown))
-// CHECK-32-NEXT: (field name=t14 offset=88
+// CHECK-32-NEXT: (field name=t14 offset=80
// CHECK-32-NEXT: (reference kind=strong refcounting=unknown))
-// CHECK-32-NEXT: (field name=t15 offset=92
+// CHECK-32-NEXT: (field name=t15 offset=84
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// (unstable implementation details omitted)
-// CHECK-32: (field name=t16 offset=96
+// CHECK-32: (field name=t16 offset=88
// CHECK-32-NEXT: (struct size=12 alignment=4 stride=12 num_extra_inhabitants=0
// (unstable implementation details omitted)
-// CHECK-32: (field name=t17 offset=108
+// CHECK-32: (field name=t17 offset=100
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t18 offset=112
+// CHECK-32-NEXT: (field name=t18 offset=104
// CHECK-32-NEXT: (struct size=2 alignment=2 stride=2 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=2 alignment=2 stride=2 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t19 offset=116
+// CHECK-32-NEXT: (field name=t19 offset=108
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t20 offset=120
+// CHECK-32-NEXT: (field name=t20 offset=112
// CHECK-32-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t21 offset=128
+// CHECK-32-NEXT: (field name=t21 offset=120
// CHECK-32-NEXT: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=0)))))
diff --git a/validation-test/stdlib/FloatingPointConversion.swift.gyb b/validation-test/stdlib/FloatingPointConversion.swift.gyb
index 9882102..3a96da7 100644
--- a/validation-test/stdlib/FloatingPointConversion.swift.gyb
+++ b/validation-test/stdlib/FloatingPointConversion.swift.gyb
@@ -115,75 +115,59 @@
% end # for in all_floating_point_types (Other)
-%{
-
-float_to_int_conversion_template = gyb.parse_template("float_to_int_conversion",
-"""
-% for int_ty in all_integer_types(word_bits):
-% OtherInt = int_ty.stdlib_name
-% OtherMin = int_ty.min
-% OtherMax = int_ty.max
-% (FloatMin, FloatMax) = getFtoIBounds(self_type.bits, int_ty.bits, int_ty.is_signed)
-
-% for testValue in [0, FloatMin, FloatMax, FloatMin - 1, FloatMax + 1, OtherMin, OtherMax]:
-
-% if testValue < OtherMin or testValue > OtherMax:
-% # Can't construct `other` value, do nothing and continue.
-
-% elif testValue >= FloatMin and testValue <= FloatMax:
-
-FixedPointConversionTruncations.test("${OtherInt}to${Self}Conversion/${testValue}") {
- expectEqual(${Self}(${testValue} as ${OtherInt}), ${testValue})
-}
-
-FixedPointConversionFailures.test("${OtherInt}to${Self}FailableConversion/${testValue}") {
- expectEqual(${Self}(exactly: ${testValue} as ${OtherInt}), ${testValue})
-}
-
-% else:
-
-FixedPointConversionTruncations.test("${OtherInt}to${Self}Truncation/${testValue}") {
- let value: ${OtherInt} = ${testValue}
- let result = ${Self}(value)
- expectNotEqual(${OtherInt}(result), value)
-}
-
-FixedPointConversionFailures.test("${OtherInt}to${Self}Failure/${testValue}") {
- let value: ${OtherInt} = ${testValue}
- let result = ${Self}(exactly: value)
- expectEqual(result, ${OtherMin} as ${Self})
- expectEqual(${OtherInt}(result!), value)
-}
-
-% end
-
-% end # testValue in testValues
-% end # for in all_integer_types (Other)
-""")
-}%
-
#if arch(i386) || arch(arm)
-
- ${gyb.execute_template(
- float_to_int_conversion_template,
- word_bits=32,
- **locals()
- )}
-
+% int_types = all_integer_types(32)
#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x)
-
- ${gyb.execute_template(
- float_to_int_conversion_template,
- word_bits=64,
- **locals()
- )}
-
+% int_types = all_integer_types(64)
#else
-
_UnimplementedError()
-
#endif
+% for int_ty in int_types:
+% OtherInt = int_ty.stdlib_name
+
+extension ${OtherInt} {
+ static var _test${Self}Conversion: [(${OtherInt}, ${OtherInt}, ${OtherInt}?)] {
+ if bitWidth > ${Self}.significandBitCount + 1 {
+ let bitOffset = ${Self}.significandBitCount + 1
+ let limit: ${OtherInt} = ~(~0 << bitOffset)
+ let over: ${OtherInt} = 1 + limit << 1
+ return [
+ (0, 0, 0),
+ (limit, limit, limit),
+ (over, over + 1, nil),
+% if int_ty.is_signed:
+ (-limit, -limit, -limit),
+ (-over, -(over + 1), nil),
+% end
+ ]
+ } else {
+ return [
+ (0, 0, 0),
+ (.min, .min, .min),
+ (.max, .max, .max),
+ ]
+ }
+ }
+}
+
+FixedPointConversionTruncations.test("${OtherInt}to${Self}")
+ .forEach(in: ${OtherInt}._test${Self}Conversion) {
+ value, roundedExpectation, exactExpectation in
+
+ let roundedResult = ${Self}(value)
+ expectEqual(roundedResult, ${Self}(roundedExpectation))
+
+ let exactResult = ${Self}(exactly: value)
+ if let expectation = exactExpectation {
+ expectEqual(exactResult!, ${Self}(expectation))
+ } else {
+ expectNil(exactResult)
+ }
+}
+
+% end # for in int_types
+
% if Self == 'Float80':
#endif
% end
diff --git a/validation-test/stdlib/ValidationNSNumberBridging.swift b/validation-test/stdlib/ValidationNSNumberBridging.swift
index 3e99a47..61255c4 100644
--- a/validation-test/stdlib/ValidationNSNumberBridging.swift
+++ b/validation-test/stdlib/ValidationNSNumberBridging.swift
@@ -652,16 +652,16 @@
let uint = (number!) as? UInt
expectEqual(UInt(exactly: interestingValue), uint)
- // these are disabled because of https://bugs.swift.org/browse/SR-4634
- if uint! != UInt(UInt32.max) && uint! != UInt(UInt32.max - 1) {
- let float = (number!) as? Float
- let expectedFloat = Float(uint!)
- testFloat(expectedFloat, float)
+ let float = (number!) as? Float
+ let expectedFloat = Float(exactly: uint!)
+ if UInt.bitWidth == 32 && uint! >= UInt.max - 1 {
+ expectNil(expectedFloat)
+ } else {
+ testFloat(expectedFloat, float)
}
-
-
+
let double = (number!) as? Double
- let expectedDouble = Double(uint!)
+ let expectedDouble = Double(exactly: uint!)
testDouble(expectedDouble, double)
}
let bridged = interestingValue as NSNumber