Merge pull request #7160 from rintaro/3.1-codecomplete-override-protocol
[3.1][CodeComplete] Don't emit 'override' in protocol extension
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3bd4d0b..e54bb8e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,11 @@
Swift 3.1
---------
+* [SE-0080][]:
+
+ Adds a new family of conversion initializers to all numeric types that
+ either complete successfully without loss of information or return nil.
+
* Swift will now warn when an `NSObject` subclass attempts to override the
class `initialize` method. Swift doesn't guarantee that references to class
names trigger Objective-C class realization if they have no other
diff --git a/include/swift/AST/AnyFunctionRef.h b/include/swift/AST/AnyFunctionRef.h
index c2e1a90..2d5e1fb 100644
--- a/include/swift/AST/AnyFunctionRef.h
+++ b/include/swift/AST/AnyFunctionRef.h
@@ -176,6 +176,16 @@
}
llvm_unreachable("unexpected AnyFunctionRef representation");
}
+
+ GenericSignature *getGenericSignature() const {
+ if (auto afd = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
+ return afd->getGenericSignature();
+ }
+ if (auto ce = TheFunction.dyn_cast<AbstractClosureExpr *>()) {
+ return ce->getGenericSignatureOfContext();
+ }
+ llvm_unreachable("unexpected AnyFunctionRef representation");
+ }
};
#if SWIFT_COMPILER_IS_MSVC
#pragma warning(pop)
diff --git a/include/swift/AST/GenericSignature.h b/include/swift/AST/GenericSignature.h
index 275d8b4..21125b2 100644
--- a/include/swift/AST/GenericSignature.h
+++ b/include/swift/AST/GenericSignature.h
@@ -141,6 +141,12 @@
void getSubstitutionMap(ArrayRef<Substitution> args,
SubstitutionMap &subMap) const;
+ /// Build an interface type substitution map from a type substitution function
+ /// and conformance lookup function.
+ SubstitutionMap
+ getSubstitutionMap(TypeSubstitutionFn subs,
+ LookupConformanceFn lookupConformance) const;
+
using GenericFunction = auto(CanType canType, Type conformingReplacementType,
ProtocolType *conformedProtocol)
->Optional<ProtocolConformanceRef>;
diff --git a/include/swift/AST/SubstitutionMap.h b/include/swift/AST/SubstitutionMap.h
index 637206e..d0c2848 100644
--- a/include/swift/AST/SubstitutionMap.h
+++ b/include/swift/AST/SubstitutionMap.h
@@ -94,6 +94,22 @@
GenericSignature *derivedSig,
Optional<SubstitutionMap> derivedSubs,
LazyResolver *resolver);
+
+ /// Combine two substitution maps as follows.
+ ///
+ /// The result is written in terms of the generic parameters of 'baseSig'.
+ ///
+ /// Generic parameters with a depth less than 'baseDepth' come from
+ /// 'baseSubs'.
+ ///
+ /// Generic parameters with a depth greater than 'baseDepth' come from
+ /// 'origSubs', but are looked up starting with a depth of 'origDepth'.
+ static SubstitutionMap
+ combineSubstitutionMaps(const SubstitutionMap &baseSubMap,
+ const SubstitutionMap &origSubMap,
+ unsigned baseDepth,
+ unsigned origDepth,
+ GenericSignature *baseSig);
};
} // end namespace swift
diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h
index 7b05a44..5b1f17c 100644
--- a/include/swift/Basic/LangOptions.h
+++ b/include/swift/Basic/LangOptions.h
@@ -133,7 +133,7 @@
/// \brief The upper bound, in bytes, of temporary data that can be
/// allocated by the constraint solver.
- unsigned SolverMemoryThreshold = 33554432; /* 32 * 1024 * 1024 */
+ unsigned SolverMemoryThreshold = 512 * 1024 * 1024;
unsigned SolverBindingThreshold = 1024 * 1024;
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index e0a9210..a8ee3c2 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -498,9 +498,46 @@
using OwnedProtocolDescriptorRef =
std::unique_ptr<const TargetProtocolDescriptor<Runtime>, delete_with_free>;
- /// Cached isa mask.
- StoredPointer isaMask;
- bool hasIsaMask = false;
+ enum class IsaEncodingKind {
+ /// We haven't checked yet.
+ Unknown,
+
+ /// There was an error trying to find out the isa encoding.
+ Error,
+
+ /// There's no special isa encoding.
+ None,
+
+ /// There's an unconditional mask to apply to the isa pointer.
+ /// - IsaMask stores the mask.
+ Masked,
+
+ /// Isa pointers are indexed. If applying a mask yields a magic value,
+ /// applying a different mask and shifting yields an index into a global
+ /// array of class pointers. Otherwise, the isa pointer is just a raw
+ /// class pointer.
+ /// - IsaIndexMask stores the index mask.
+ /// - IsaIndexShift stores the index shift.
+ /// - IsaMagicMask stores the magic value mask.
+ /// - IsaMagicValue stores the magic value.
+ /// - IndexedClassesPointer stores the pointer to the start of the
+ /// indexed classes array; this is constant throughout the program.
+ /// - IndexedClassesCountPointer stores a pointer to the number
+ /// of elements in the indexed classes array.
+ Indexed
+ };
+
+ IsaEncodingKind IsaEncoding = IsaEncodingKind::Unknown;
+ union {
+ StoredPointer IsaMask;
+ StoredPointer IsaIndexMask;
+ };
+ StoredPointer IsaIndexShift;
+ StoredPointer IsaMagicMask;
+ StoredPointer IsaMagicValue;
+ StoredPointer IndexedClassesPointer;
+ StoredPointer IndexedClassesCountPointer;
+ StoredPointer LastIndexedClassesCount = 0;
public:
BuilderType Builder;
@@ -535,15 +572,12 @@
/// Get the remote process's swift_isaMask.
std::pair<bool, StoredPointer> readIsaMask() {
- auto address = Reader->getSymbolAddress("swift_isaMask");
- if (!address)
- return {false, 0};
+ auto encoding = getIsaEncoding();
+ if (encoding != IsaEncodingKind::Masked)
+ // Still return success if there's no isa encoding at all.
+ return {encoding == IsaEncodingKind::None, 0};
- if (!Reader->readInteger(address, &isaMask))
- return {false, 0};
-
- hasIsaMask = true;
- return {true, isaMask};
+ return {true, IsaMask};
}
/// Given a remote pointer to metadata, attempt to discover its MetadataKind.
@@ -774,20 +808,64 @@
/// Read the isa pointer of a class or closure context instance and apply
/// the isa mask.
- std::pair<bool, StoredPointer> readMetadataFromInstance(
- StoredPointer ObjectAddress) {
- StoredPointer isaMaskValue = ~0;
- auto isaMask = readIsaMask();
- if (isaMask.first)
- isaMaskValue = isaMask.second;
-
- StoredPointer MetadataAddress;
- if (!Reader->readBytes(RemoteAddress(ObjectAddress),
- (uint8_t*)&MetadataAddress,
- sizeof(StoredPointer)))
+ std::pair<bool, StoredPointer>
+ readMetadataFromInstance(StoredPointer objectAddress) {
+ StoredPointer isa;
+ if (!Reader->readInteger(RemoteAddress(objectAddress), &isa))
return {false, 0};
- return {true, MetadataAddress & isaMaskValue};
+ switch (getIsaEncoding()) {
+ case IsaEncodingKind::Unknown:
+ case IsaEncodingKind::Error:
+ return {false, 0};
+
+ case IsaEncodingKind::None:
+ return {true, isa};
+
+ case IsaEncodingKind::Masked:
+ return {true, isa & IsaMask};
+
+ case IsaEncodingKind::Indexed: {
+ // If applying the magic mask doesn't give us the magic value,
+ // it's not an indexed isa.
+ if ((isa & IsaMagicMask) != IsaMagicValue)
+ return {true, isa};
+
+ // Extract the index.
+ auto classIndex = (isa & IsaIndexMask) >> IsaIndexShift;
+
+ // 0 is never a valid index.
+ if (classIndex == 0) {
+ return {false, 0};
+
+ // If the index is out of range, it's an error; but check for an
+ // update first. (This will also trigger the first time because
+ // we initialize LastIndexedClassesCount to 0).
+ } else if (classIndex >= LastIndexedClassesCount) {
+ StoredPointer count;
+ if (!Reader->readInteger(RemoteAddress(IndexedClassesCountPointer),
+ &count)) {
+ return {false, 0};
+ }
+
+ LastIndexedClassesCount = count;
+ if (classIndex >= count) {
+ return {false, 0};
+ }
+ }
+
+ // Find the address of the appropriate array element.
+ RemoteAddress eltPointer =
+ RemoteAddress(IndexedClassesPointer
+ + classIndex * sizeof(StoredPointer));
+ StoredPointer metadataPointer;
+ if (!Reader->readInteger(eltPointer, &metadataPointer)) {
+ return {false, 0};
+ }
+
+ return {true, metadataPointer};
+ }
+ }
}
/// Read the parent type metadata from a nested nominal type metadata.
@@ -1241,6 +1319,66 @@
return dataPtr;
}
+ IsaEncodingKind getIsaEncoding() {
+ if (IsaEncoding != IsaEncodingKind::Unknown)
+ return IsaEncoding;
+
+ auto finish = [&](IsaEncodingKind result) -> IsaEncodingKind {
+ IsaEncoding = result;
+ return result;
+ };
+
+ /// Look up the given global symbol and bind 'varname' to its
+ /// address if its exists.
+# define tryFindSymbol(varname, symbolName) \
+ auto varname = Reader->getSymbolAddress(symbolName); \
+ if (!varname) \
+ return finish(IsaEncodingKind::Error)
+ /// Read from the given pointer into 'dest'.
+# define tryReadSymbol(varname, dest) do { \
+ if (!Reader->readInteger(varname, &dest)) \
+ return finish(IsaEncodingKind::Error); \
+ } while (0)
+ /// Read from the given global symbol into 'dest'.
+# define tryFindAndReadSymbol(dest, symbolName) do { \
+ tryFindSymbol(_address, symbolName); \
+ tryReadSymbol(_address, dest); \
+ } while (0)
+
+ // Check for the magic-mask symbol that indicates that the ObjC
+ // runtime is using indexed ISAs.
+ if (auto magicMaskAddress =
+ Reader->getSymbolAddress("objc_debug_indexed_isa_magic_mask")) {
+ tryReadSymbol(magicMaskAddress, IsaMagicMask);
+ if (IsaMagicMask != 0) {
+ tryFindAndReadSymbol(IsaMagicValue,
+ "objc_debug_indexed_isa_magic_value");
+ tryFindAndReadSymbol(IsaIndexMask,
+ "objc_debug_indexed_isa_index_mask");
+ tryFindAndReadSymbol(IsaIndexShift,
+ "objc_debug_indexed_isa_index_shift");
+ tryFindSymbol(indexedClasses, "objc_indexed_classes");
+ IndexedClassesPointer = indexedClasses.getAddressData();
+ tryFindSymbol(indexedClassesCount, "objc_indexed_classes_count");
+ IndexedClassesCountPointer = indexedClassesCount.getAddressData();
+
+ return finish(IsaEncodingKind::Indexed);
+ }
+ }
+
+ // Check for the ISA mask symbol. This has to come second because
+ // the standard library will define this even if the ObjC runtime
+ // doesn't use it.
+ if (auto maskAddress = Reader->getSymbolAddress("swift_isaMask")) {
+ tryReadSymbol(maskAddress, IsaMask);
+ if (IsaMask != 0) {
+ return finish(IsaEncodingKind::Masked);
+ }
+ }
+
+ return finish(IsaEncodingKind::None);
+ }
+
template <class T>
static constexpr T roundUpToAlignment(T offset, T alignment) {
return (offset + alignment - 1) & ~(alignment - 1);
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 9388af8..41ca035 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 = 308; // Last change: nested type table
+const uint16_t VERSION_MINOR = 309; // Last change: static/non-static values
using DeclID = PointerEmbeddedInt<unsigned, 31>;
using DeclIDField = BCFixed<31>;
@@ -1179,7 +1179,8 @@
XREF_VALUE_PATH_PIECE,
TypeIDField, // type
IdentifierIDField, // name
- BCFixed<1> // restrict to protocol extension
+ BCFixed<1>, // restrict to protocol extension
+ BCFixed<1> // static?
>;
using XRefInitializerPathPieceLayout = BCRecordLayout<
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 8477140..63b6d80 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1587,6 +1587,7 @@
if (Impl.CurrentConstraintSolverArena) {
Size += Impl.CurrentConstraintSolverArena->getTotalMemory();
+ Size += Impl.CurrentConstraintSolverArena->Allocator.getBytesAllocated();
}
return Size;
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 462fcd5..3daf7f1 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2452,6 +2452,11 @@
if (!ctor)
continue;
+ // Swift initializers added in extensions of Objective-C classes can never
+ // be overrides.
+ if (hasClangNode() && !ctor->hasClangNode())
+ return false;
+
// Resolve this initializer, if needed.
if (!ctor->hasInterfaceType())
resolver->resolveDeclSignature(ctor);
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index 547504a..0c6a772 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -346,6 +346,64 @@
assert(subs.empty() && "did not use all substitutions?!");
}
+SubstitutionMap
+GenericSignature::
+getSubstitutionMap(TypeSubstitutionFn subs,
+ GenericSignature::LookupConformanceFn lookupConformance) const {
+ SubstitutionMap subMap;
+
+ // Enumerate all of the requirements that require substitution.
+ enumeratePairedRequirements([&](Type depTy, ArrayRef<Requirement> reqs) {
+ auto canTy = depTy->getCanonicalType();
+
+ // Compute the replacement type.
+ Type currentReplacement = depTy.subst(subs, lookupConformance,
+ SubstFlags::UseErrorType);
+ if (auto substTy = dyn_cast<SubstitutableType>(canTy))
+ subMap.addSubstitution(substTy, currentReplacement);
+
+ // Collect the conformances.
+ SmallVector<ProtocolConformanceRef, 2> conformances;
+ for (auto req: reqs) {
+ assert(req.getKind() == RequirementKind::Conformance);
+ auto protoType = req.getSecondType()->castTo<ProtocolType>();
+ if (auto conformance = lookupConformance(canTy,
+ currentReplacement,
+ protoType)) {
+ conformances.push_back(*conformance);
+ }
+ }
+ subMap.addConformances(canTy, getASTContext().AllocateCopy(conformances));
+
+ return false;
+ });
+
+ for (auto reqt : getRequirements()) {
+ if (reqt.getKind() != RequirementKind::SameType)
+ continue;
+
+ auto first = reqt.getFirstType();
+ auto second = reqt.getSecondType();
+
+ if (!first->isTypeParameter() || !second->isTypeParameter())
+ continue;
+
+ if (auto *firstMemTy = first->getAs<DependentMemberType>()) {
+ subMap.addParent(second->getCanonicalType(),
+ firstMemTy->getBase()->getCanonicalType(),
+ firstMemTy->getAssocType());
+ }
+
+ if (auto *secondMemTy = second->getAs<DependentMemberType>()) {
+ subMap.addParent(first->getCanonicalType(),
+ secondMemTy->getBase()->getCanonicalType(),
+ secondMemTy->getAssocType());
+ }
+ }
+
+ return subMap;
+}
+
SmallVector<Type, 4> GenericSignature::getAllDependentTypes() const {
SmallVector<Type, 4> result;
enumeratePairedRequirements([&](Type type, ArrayRef<Requirement>) {
diff --git a/lib/AST/Parameter.cpp b/lib/AST/Parameter.cpp
index 8657add..52fde3f 100644
--- a/lib/AST/Parameter.cpp
+++ b/lib/AST/Parameter.cpp
@@ -88,7 +88,8 @@
// Remap the ParamDecls inside of the ParameterList.
for (auto &decl : params) {
- bool hadDefaultArgument =decl->getDefaultValue() != nullptr;
+ bool hadDefaultArgument =
+ decl->getDefaultArgumentKind() == DefaultArgumentKind::Normal;
decl = new (C) ParamDecl(decl);
if (options & Implicit)
@@ -101,8 +102,12 @@
decl->setName(C.getIdentifier("argument"));
// If we're inheriting a default argument, mark it as such.
- if (hadDefaultArgument && (options & Inherited)) {
- decl->setDefaultArgumentKind(DefaultArgumentKind::Inherited);
+ // FIXME: Figure out how to clone default arguments as well.
+ if (hadDefaultArgument) {
+ if (options & Inherited)
+ decl->setDefaultArgumentKind(DefaultArgumentKind::Inherited);
+ else
+ decl->setDefaultArgumentKind(DefaultArgumentKind::None);
}
}
diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp
index 9a5e48c..7919fe0 100644
--- a/lib/AST/SubstitutionMap.cpp
+++ b/lib/AST/SubstitutionMap.cpp
@@ -226,3 +226,37 @@
return subMap;
}
+
+SubstitutionMap
+SubstitutionMap::combineSubstitutionMaps(const SubstitutionMap &baseSubMap,
+ const SubstitutionMap &origSubMap,
+ unsigned baseDepth,
+ unsigned origDepth,
+ GenericSignature *baseSig) {
+ auto replaceGenericParameter = [&](Type type) -> Type {
+ if (auto gp = type->getAs<GenericTypeParamType>()) {
+ if (gp->getDepth() < baseDepth) return Type();
+ return GenericTypeParamType::get(gp->getDepth() + origDepth - baseDepth,
+ gp->getIndex(),
+ baseSig->getASTContext());
+ }
+
+ return type;
+ };
+
+ return baseSig->getSubstitutionMap(
+ [&](SubstitutableType *type) {
+ auto replacement = replaceGenericParameter(type);
+ if (replacement)
+ return Type(replacement).subst(origSubMap);
+ return Type(type).subst(baseSubMap);
+ },
+ [&](CanType type, Type substType, ProtocolType *conformedProtocol) {
+ auto replacement = type.transform(replaceGenericParameter);
+ if (replacement)
+ return origSubMap.lookupConformance(replacement->getCanonicalType(),
+ conformedProtocol->getDecl());
+ return baseSubMap.lookupConformance(type,
+ conformedProtocol->getDecl());
+ });
+}
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 8d2986c..a6cb880 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -1279,7 +1279,7 @@
JobAction *PCH = nullptr;
if (Args.hasFlag(options::OPT_enable_bridging_pch,
options::OPT_disable_bridging_pch,
- false)) {
+ true)) {
if (Arg *A = Args.getLastArg(options::OPT_import_objc_header)) {
StringRef Value = A->getValue();
auto Ty = TC.lookupTypeForExtension(llvm::sys::path::extension(Value));
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index d788a4a..32389f5 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -23,6 +23,7 @@
#include "swift/AST/Decl.h"
#include "swift/AST/DiagnosticsSIL.h"
#include "swift/AST/ForeignErrorConvention.h"
+#include "swift/AST/GenericEnvironment.h"
#include "swift/Basic/Fallthrough.h"
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
#include "clang/AST/Attr.h"
@@ -742,9 +743,17 @@
// from the function to which the argument is attached.
if (constant && !constant->isDefaultArgGenerator())
if (auto function = constant->getAnyFunctionRef()) {
- auto getCanonicalType = [&](Type t) -> CanType {
- if (genericSig)
- return genericSig->getCanonicalTypeInContext(t, *M.getSwiftModule());
+ // NB: The generic signature may be elided from the lowered function type
+ // if the function is in a fully-specialized context, but we still need to
+ // canonicalize references to the generic parameters that may appear in
+ // non-canonical types in that context. We need the original generic
+ // signature from the AST for that.
+ auto origGenericSig
+ = function->getGenericSignature();
+ auto getCanonicalType = [origGenericSig, &M](Type t) -> CanType {
+ if (origGenericSig)
+ return origGenericSig->getCanonicalTypeInContext(t,
+ *M.getSwiftModule());
return t->getCanonicalType();
};
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index da454b1..9d6ef43 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -118,6 +118,11 @@
if (funcDecl->isFinal())
return true;
+ // Extension methods currently must be statically dispatched, unless they're
+ // @objc or dynamic.
+ if (funcDecl->getDeclContext()->isExtensionContext()
+ && !constant.isForeign)
+ return true;
// We cannot form a direct reference to a method body defined in
// Objective-C.
@@ -3657,11 +3662,13 @@
// Emit the inner expression.
SmallVector<ManagedValue, 8> innerArgs;
SmallVector<InOutArgument, 2> innerInOutArgs;
- ArgEmitter(SGF, Rep, ClaimedParamsRef(innerParams), innerArgs, innerInOutArgs,
- /*foreign error*/ None, /*foreign self*/ ImportAsMemberStatus(),
- (innerSpecialDests ? ArgSpecialDestArray(*innerSpecialDests)
- : Optional<ArgSpecialDestArray>()))
- .emitTopLevel(ArgumentSource(inner), innerOrigParamType);
+ if (!innerParams.empty()) {
+ ArgEmitter(SGF, Rep, ClaimedParamsRef(innerParams), innerArgs, innerInOutArgs,
+ /*foreign error*/ None, /*foreign self*/ ImportAsMemberStatus(),
+ (innerSpecialDests ? ArgSpecialDestArray(*innerSpecialDests)
+ : Optional<ArgSpecialDestArray>()))
+ .emitTopLevel(ArgumentSource(inner), innerOrigParamType);
+ }
// Make a second pass to split the inner arguments correctly.
{
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index 81d77ab..fda53db 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -2065,7 +2065,8 @@
if (varStorageType.is<ReferenceStorageType>()) {
auto formalRValueType =
- ivar->getType()->getRValueType()->getReferenceStorageReferent()
+ ivar->getDeclContext()->mapTypeIntoContext(ivar->getInterfaceType())
+ ->getReferenceStorageReferent()
->getCanonicalType();
auto typeData =
getPhysicalStorageTypeData(SGM, ivar, formalRValueType);
diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp
index 670e9b2..3fbfeba 100644
--- a/lib/SILGen/SILGenProlog.cpp
+++ b/lib/SILGen/SILGenProlog.cpp
@@ -344,7 +344,9 @@
}
}
-static void emitCaptureArguments(SILGenFunction &gen, CapturedValue capture,
+static void emitCaptureArguments(SILGenFunction &gen,
+ AnyFunctionRef closure,
+ CapturedValue capture,
unsigned ArgNo) {
auto *VD = capture.getDecl();
@@ -357,7 +359,12 @@
auto interfaceType = cast<VarDecl>(VD)->getInterfaceType();
if (!interfaceType->hasTypeParameter()) return interfaceType;
- auto genericEnv = gen.F.getGenericEnvironment();
+ // NB: The generic signature may be elided from the lowered function type
+ // if the function is in a fully-specialized context, but we still need to
+ // canonicalize references to the generic parameters that may appear in
+ // non-canonical types in that context. We need the original generic
+ // environment from the AST for that.
+ auto genericEnv = closure.getGenericEnvironment();
return genericEnv->mapTypeIntoContext(gen.F.getModule().getSwiftModule(),
interfaceType);
};
@@ -446,7 +453,7 @@
return;
}
- emitCaptureArguments(*this, capture, ++ArgNo);
+ emitCaptureArguments(*this, TheClosure, capture, ++ArgNo);
}
}
diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp
index 84f56ad..38b056f 100644
--- a/lib/SILOptimizer/Utils/Devirtualize.cpp
+++ b/lib/SILOptimizer/Utils/Devirtualize.cpp
@@ -426,80 +426,56 @@
if (!baseCalleeType->isPolymorphic())
return;
- auto derivedClass = derivedSelfType;
- if (auto metatypeType = dyn_cast<MetatypeType>(derivedClass))
- derivedClass = CanType(metatypeType->getInstanceType());
-
- SubstitutionMap subMap;
-
- if (auto origCalleeSig = AI.getOrigCalleeType()->getGenericSignature()) {
- auto calleeSelfType = AI.getSubstCalleeType()->getSelfParameter().getType();
- if (auto metatypeType = dyn_cast<MetatypeType>(calleeSelfType))
- calleeSelfType = CanType(metatypeType->getInstanceType());
- auto *calleeClassDecl = calleeSelfType->getClassOrBoundGenericClass();
- assert(calleeClassDecl && "self is not a class type");
-
- auto origSubs = AI.getSubstitutions();
-
- // Add generic parameters from the method itself, ignoring any generic
- // parameters from the derived class.
- unsigned minDepth = 0;
- if (auto derivedClassSig = calleeClassDecl->getGenericSignatureOfContext())
- minDepth = derivedClassSig->getGenericParams().back()->getDepth() + 1;
-
- for (auto depTy : origCalleeSig->getAllDependentTypes()) {
- // Grab the next substitution.
- auto sub = origSubs.front();
- origSubs = origSubs.slice(1);
-
- // If the dependent type doesn't contain any generic parameter with
- // a depth of at least the minimum, skip this type.
- auto canTy = depTy->getCanonicalType();
- auto hasInnerGenericParameter = [minDepth](Type type) -> bool {
- if (auto gp = type->getAs<GenericTypeParamType>()) {
- return gp->getDepth() >= minDepth;
- }
- return false;
- };
-
- if (!Type(canTy.getPointer()).findIf(hasInnerGenericParameter))
- continue;
-
- // Otherwise, record the replacement and conformances for the mapped
- // type.
- if (isa<SubstitutableType>(canTy)) {
- subMap.addSubstitution(cast<SubstitutableType>(canTy),
- sub.getReplacement());
- }
- subMap.addConformances(canTy, sub.getConformances());
- }
- assert(origSubs.empty());
- }
-
// Add any generic substitutions for the base class.
- auto baseSelfType = baseCalleeType->getSelfParameter().getType();
- if (auto metatypeType = dyn_cast<MetatypeType>(baseSelfType))
- baseSelfType = CanType(metatypeType->getInstanceType());
+ Type baseSelfType = baseCalleeType->getSelfParameter().getType();
+ if (auto metatypeType = baseSelfType->getAs<MetatypeType>())
+ baseSelfType = metatypeType->getInstanceType();
- auto *baseClassDecl = baseSelfType.getClassOrBoundGenericClass();
+ auto *baseClassDecl = baseSelfType->getClassOrBoundGenericClass();
assert(baseClassDecl && "not a class method");
+ unsigned baseDepth = 0;
+ SubstitutionMap baseSubMap;
if (auto baseClassSig = baseClassDecl->getGenericSignatureOfContext()) {
+ baseDepth = baseClassSig->getGenericParams().back()->getDepth() + 1;
+
// Compute the type of the base class, starting from the
// derived class type and the type of the method's self
// parameter.
- auto baseClass = derivedClass->getSuperclassForDecl(baseClassDecl, nullptr)
- ->getCanonicalType();
- auto baseClassSubs = baseClass->gatherAllSubstitutions(
+ Type derivedClass = derivedSelfType;
+ if (auto metatypeType = derivedClass->getAs<MetatypeType>())
+ derivedClass = metatypeType->getInstanceType();
+ auto baseClass = derivedClass->getSuperclassForDecl(baseClassDecl, nullptr);
+ auto subs = baseClass->gatherAllSubstitutions(
M.getSwiftModule(), nullptr);
-
- // Decompose the base class substitutions, adding them to the same
- // substitution maps as above.
- baseClassSig->getSubstitutionMap(baseClassSubs, subMap);
+ baseSubMap = baseClassSig->getSubstitutionMap(subs);
}
- // Build the new substitutions using the base method signature.
+ SubstitutionMap origSubMap;
+ if (auto origCalleeSig = AI.getOrigCalleeType()->getGenericSignature())
+ origSubMap = origCalleeSig->getSubstitutionMap(AI.getSubstitutions());
+
+ Type calleeSelfType = AI.getOrigCalleeType()->getSelfParameter().getType();
+ if (auto metatypeType = calleeSelfType->getAs<MetatypeType>())
+ calleeSelfType = metatypeType->getInstanceType();
+ auto *calleeClassDecl = calleeSelfType->getClassOrBoundGenericClass();
+ assert(calleeClassDecl && "self is not a class type");
+
+ // Add generic parameters from the method itself, ignoring any generic
+ // parameters from the derived class.
+ unsigned origDepth = 0;
+ if (auto calleeClassSig = calleeClassDecl->getGenericSignatureOfContext())
+ origDepth = calleeClassSig->getGenericParams().back()->getDepth() + 1;
+
auto baseCalleeSig = baseCalleeType->getGenericSignature();
+
+ auto subMap = SubstitutionMap::combineSubstitutionMaps(baseSubMap,
+ origSubMap,
+ baseDepth,
+ origDepth,
+ baseCalleeSig);
+
+ // Build the new substitutions using the base method signature.
baseCalleeSig->getSubstitutions(subMap, newSubs);
}
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 4073c77..17839e6 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -2099,45 +2099,32 @@
// Create a tuple containing all of the segments.
SmallVector<Expr *, 4> segments;
SmallVector<Identifier, 4> names;
- unsigned index = 0;
ConstraintLocatorBuilder locatorBuilder(cs.getConstraintLocator(expr));
for (auto segment : expr->getSegments()) {
- auto locator = cs.getConstraintLocator(
- locatorBuilder.withPathElement(
- LocatorPathElt::getInterpolationArgument(index++)));
-
- // Find the initializer we chose.
- auto choice = getOverloadChoice(locator);
-
- auto memberRef = buildMemberRef(
- typeRef, choice.openedFullType,
- segment->getStartLoc(), choice.choice.getDecl(),
- DeclNameLoc(segment->getStartLoc()),
- choice.openedType,
- locator, locator, /*Implicit=*/true,
- choice.choice.getFunctionRefKind(),
- AccessSemantics::Ordinary,
- /*isDynamic=*/false);
ApplyExpr *apply =
CallExpr::createImplicit(
- tc.Context, memberRef,
+ tc.Context, typeRef,
{ segment },
{ tc.Context.Id_stringInterpolationSegment });
cs.cacheType(apply->getArg());
- auto converted = finishApply(apply, openedType, locatorBuilder);
- if (!converted)
- return nullptr;
+ Expr *convertedSegment = apply;
+ if (tc.typeCheckExpressionShallow(convertedSegment, cs.DC))
+ continue;
- segments.push_back(converted);
+ segments.push_back(convertedSegment);
- if (index == 1) {
+ if (names.empty()) {
names.push_back(tc.Context.Id_stringInterpolation);
} else {
names.push_back(Identifier());
}
}
+ // If all of the segments had errors, bail out.
+ if (segments.empty())
+ return nullptr;
+
// Call the init(stringInterpolation:) initializer with the arguments.
ApplyExpr *apply = CallExpr::createImplicit(tc.Context, memberRef,
segments, names);
@@ -4115,22 +4102,7 @@
unsigned newFlags = locator->getSummaryFlags();
- // If we have an interpolation argument, dig out the constructor if we
- // can.
- // FIXME: This representation is actually quite awful
- if (newPath.size() == 1 &&
- newPath[0].getKind() == ConstraintLocator::InterpolationArgument) {
- newPath.push_back(ConstraintLocator::ConstructorMember);
-
- locator = cs.getConstraintLocator(locator->getAnchor(), newPath, newFlags);
- auto known = solution.overloadChoices.find(locator);
- if (known != solution.overloadChoices.end()) {
- auto &choice = known->second.choice;
- if (choice.getKind() == OverloadChoiceKind::Decl)
- return cast<AbstractFunctionDecl>(choice.getDecl());
- }
- return nullptr;
- } else if (isSubscript) {
+ if (isSubscript) {
newPath.push_back(ConstraintLocator::SubscriptMember);
} else {
newPath.push_back(ConstraintLocator::ApplyFunction);
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 3eb1607..98d7b34 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -222,22 +222,6 @@
}
break;
- case ConstraintLocator::InterpolationArgument:
- if (auto interp = dyn_cast<InterpolatedStringLiteralExpr>(anchor)) {
- unsigned index = path[0].getValue();
- if (index < interp->getSegments().size()) {
- // No additional target locator information.
- // FIXME: Dig out the constructor we're trying to call?
- targetAnchor = nullptr;
- targetPath.clear();
-
- anchor = interp->getSegments()[index];
- path = path.slice(1);
- continue;
- }
- }
- break;
-
case ConstraintLocator::SubscriptIndex:
if (auto subscript = dyn_cast<SubscriptExpr>(anchor)) {
targetAnchor = subscript->getBase();
@@ -7890,7 +7874,7 @@
// Fall through to produce diagnostics.
}
- if (getExpressionTooComplex()) {
+ if (getExpressionTooComplex(viable)) {
TC.diagnose(expr->getLoc(), diag::expression_too_complex).
highlight(expr->getSourceRange());
return true;
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index a0f7585..d98a78e 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -1022,6 +1022,16 @@
DeclContext *CurDC;
SmallVector<DeclContext*, 4> DCStack;
+ static const unsigned numEditorPlaceholderVariables = 2;
+
+ /// A buffer of type variables used for editor placeholders. We only
+ /// use a small number of these (rotating through), to prevent expressions
+ /// with a large number of editor placeholders from flooding the constraint
+ /// system with type variables.
+ TypeVariableType *editorPlaceholderVariables[numEditorPlaceholderVariables]
+ = { nullptr, nullptr };
+ unsigned currentEditorPlaceholderVariable = 0;
+
/// \brief Add constraints for a reference to a named member of the given
/// base type, and return the type of such a reference.
Type addMemberRefConstraints(Expr *expr, Expr *base, DeclName name,
@@ -1224,7 +1234,6 @@
visitInterpolatedStringLiteralExpr(InterpolatedStringLiteralExpr *expr) {
// Dig out the ExpressibleByStringInterpolation protocol.
auto &tc = CS.getTypeChecker();
- auto &C = CS.getASTContext();
auto interpolationProto
= tc.getProtocol(expr->getLoc(),
KnownProtocolKind::ExpressibleByStringInterpolation);
@@ -1241,26 +1250,6 @@
interpolationProto->getDeclaredType(),
locator);
- // Each of the segments is passed as an argument to
- // init(stringInterpolationSegment:).
- unsigned index = 0;
- auto tvMeta = MetatypeType::get(tv);
- for (auto segment : expr->getSegments()) {
- auto locator = CS.getConstraintLocator(
- expr,
- LocatorPathElt::getInterpolationArgument(index++));
- auto segmentTyV = CS.createTypeVariable(locator, /*options=*/0);
- auto returnTyV = CS.createTypeVariable(locator, /*options=*/0);
- auto methodTy = FunctionType::get(segmentTyV, returnTyV);
-
- CS.addConstraint(ConstraintKind::Conversion, CS.getType(segment),
- segmentTyV, locator);
-
- DeclName segmentName(C, C.Id_init, { C.Id_stringInterpolationSegment });
- CS.addValueMemberConstraint(tvMeta, segmentName, methodTy, CurDC,
- FunctionRefKind::DoubleApply, locator);
- }
-
return tv;
}
@@ -2760,14 +2749,28 @@
Type visitEditorPlaceholderExpr(EditorPlaceholderExpr *E) {
if (E->getTypeLoc().isNull()) {
auto locator = CS.getConstraintLocator(E);
- auto placeholderTy = CS.createTypeVariable(locator, /*options*/0);
+
// A placeholder may have any type, but default to Void type if
// otherwise unconstrained.
- CS.addConstraint(ConstraintKind::Defaultable,
- placeholderTy, TupleType::getEmpty(CS.getASTContext()),
- locator);
+ auto &placeholderTy
+ = editorPlaceholderVariables[currentEditorPlaceholderVariable];
+ if (!placeholderTy) {
+ placeholderTy = CS.createTypeVariable(locator, /*options*/0);
+
+ CS.addConstraint(ConstraintKind::Defaultable,
+ placeholderTy,
+ TupleType::getEmpty(CS.getASTContext()),
+ locator);
+ }
+
+ // Move to the next placeholder variable.
+ currentEditorPlaceholderVariable
+ = (currentEditorPlaceholderVariable + 1) %
+ numEditorPlaceholderVariables;
+
return placeholderTy;
}
+
// NOTE: The type loc may be there but have failed to validate, in which
// case we return the null type.
return E->getType();
diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp
index d981565..9e14831 100644
--- a/lib/Sema/CSRanking.cpp
+++ b/lib/Sema/CSRanking.cpp
@@ -74,6 +74,9 @@
case SK_ScalarPointerConversion:
log << "scalar-to-pointer conversion";
break;
+ case SK_EmptyExistentialConversion:
+ log << "empty-existential conversion";
+ break;
}
log << ")\n";
}
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 3e4e4a5..a5a38c0 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -1558,8 +1558,10 @@
break;
case TypeKind::Tuple: {
+ assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
// Try the tuple-to-tuple conversion.
- conversionsOrFixes.push_back(ConversionRestrictionKind::TupleToTuple);
+ if (!type1->is<LValueType>())
+ conversionsOrFixes.push_back(ConversionRestrictionKind::TupleToTuple);
break;
}
@@ -1568,7 +1570,9 @@
case TypeKind::Class: {
auto nominal1 = cast<NominalType>(desugar1);
auto nominal2 = cast<NominalType>(desugar2);
- if (nominal1->getDecl() == nominal2->getDecl()) {
+ assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
+ if (!type1->is<LValueType>() &&
+ nominal1->getDecl() == nominal2->getDecl()) {
conversionsOrFixes.push_back(ConversionRestrictionKind::DeepEquality);
}
@@ -1579,7 +1583,9 @@
auto class2 = cast<ClassDecl>(nominal2->getDecl());
// CF -> Objective-C via toll-free bridging.
- if (class1->getForeignClassKind() == ClassDecl::ForeignKind::CFType &&
+ assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
+ if (!type1->is<LValueType>() &&
+ class1->getForeignClassKind() == ClassDecl::ForeignKind::CFType &&
class2->getForeignClassKind() != ClassDecl::ForeignKind::CFType &&
class1->getAttrs().hasAttribute<ObjCBridgedAttr>()) {
conversionsOrFixes.push_back(
@@ -1587,7 +1593,9 @@
}
// Objective-C -> CF via toll-free bridging.
- if (class2->getForeignClassKind() == ClassDecl::ForeignKind::CFType &&
+ assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
+ if (!type1->is<LValueType>() &&
+ class2->getForeignClassKind() == ClassDecl::ForeignKind::CFType &&
class1->getForeignClassKind() != ClassDecl::ForeignKind::CFType &&
class2->getAttrs().hasAttribute<ObjCBridgedAttr>()) {
conversionsOrFixes.push_back(
@@ -1678,7 +1686,8 @@
auto bound1 = cast<BoundGenericType>(desugar1);
auto bound2 = cast<BoundGenericType>(desugar2);
- if (bound1->getDecl() == bound2->getDecl()) {
+ assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
+ if (!type1->is<LValueType>() && bound1->getDecl() == bound2->getDecl()) {
conversionsOrFixes.push_back(ConversionRestrictionKind::DeepEquality);
}
break;
@@ -1713,12 +1722,13 @@
// there is at most one non-defaulted element.
// For non-argument tuples, we can do the same conversion but not
// to a tuple with varargs.
- if ((tuple2->getNumElements() == 1 &&
- !tuple2->getElement(0).isVararg()) ||
- (kind >= ConstraintKind::Conversion &&
- tuple2->getElementForScalarInit() >= 0 &&
- (isArgumentTupleConversion ||
- !tuple2->getVarArgsBaseType()))) {
+ if (!type1->is<LValueType>() &&
+ ((tuple2->getNumElements() == 1 &&
+ !tuple2->getElement(0).isVararg()) ||
+ (kind >= ConstraintKind::Conversion &&
+ tuple2->getElementForScalarInit() >= 0 &&
+ (isArgumentTupleConversion ||
+ !tuple2->getVarArgsBaseType())))) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::ScalarToTuple);
@@ -1732,6 +1742,7 @@
type2->getClassOrBoundGenericClass() &&
type1->getClassOrBoundGenericClass()
!= type2->getClassOrBoundGenericClass()) {
+ assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
conversionsOrFixes.push_back(ConversionRestrictionKind::Superclass);
}
@@ -1740,7 +1751,9 @@
// Don't allow this in operator contexts or we'll end up allowing
// 'T() == U()' for unrelated T and U that just happen to be Hashable.
// We can remove this special case when we implement operator hiding.
- if (kind != ConstraintKind::OperatorArgumentConversion) {
+ if (!type1->is<LValueType>() &&
+ kind != ConstraintKind::OperatorArgumentConversion) {
+ assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
conversionsOrFixes.push_back(
ConversionRestrictionKind::HashableToAnyHashable);
}
@@ -1800,16 +1813,20 @@
}
// Special implicit nominal conversions.
- if (kind >= ConstraintKind::Conversion) {
+ if (!type1->is<LValueType>() &&
+ kind >= ConstraintKind::Conversion) {
// Array -> Array.
if (isArrayType(desugar1) && isArrayType(desugar2)) {
+ assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
conversionsOrFixes.push_back(ConversionRestrictionKind::ArrayUpcast);
// Dictionary -> Dictionary.
} else if (isDictionaryType(desugar1) && isDictionaryType(desugar2)) {
+ assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
conversionsOrFixes.push_back(
ConversionRestrictionKind::DictionaryUpcast);
// Set -> Set.
} else if (isSetType(desugar1) && isSetType(desugar2)) {
+ assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
conversionsOrFixes.push_back(
ConversionRestrictionKind::SetUpcast);
}
@@ -1981,7 +1998,13 @@
// we hit commit_to_conversions below, but we have to add a token restriction
// to ensure we wrap the metatype value in a metatype erasure.
if (concrete && type2->isExistentialType() &&
+ !type1->is<LValueType>() &&
kind >= ConstraintKind::Subtype) {
+
+ // Penalize conversions to Any.
+ if (kind >= ConstraintKind::Conversion && type2->isAny())
+ increaseScore(ScoreKind::SK_EmptyExistentialConversion);
+
conversionsOrFixes.push_back(ConversionRestrictionKind::Existential);
}
@@ -1992,7 +2015,8 @@
{
BoundGenericType *boundGenericType2;
- if (concrete && kind >= ConstraintKind::Subtype &&
+ if (concrete && !type1->is<LValueType>() &&
+ kind >= ConstraintKind::Subtype &&
(boundGenericType2 = type2->getAs<BoundGenericType>())) {
auto decl2 = boundGenericType2->getDecl();
if (auto optionalKind2 = decl2->classifyAsOptionalType()) {
@@ -2011,11 +2035,13 @@
conversionsOrFixes.push_back(
ConversionRestrictionKind::OptionalToOptional);
} else if (optionalKind2 == OTK_ImplicitlyUnwrappedOptional &&
- kind >= ConstraintKind::Conversion &&
decl1 == TC.Context.getOptionalDecl()) {
- assert(boundGenericType1->getGenericArgs().size() == 1);
- conversionsOrFixes.push_back(
- ConversionRestrictionKind::OptionalToOptional);
+ if (kind >= ConstraintKind::Conversion ||
+ locator.isFunctionConversion()) {
+ assert(boundGenericType1->getGenericArgs().size() == 1);
+ conversionsOrFixes.push_back(
+ ConversionRestrictionKind::OptionalToOptional);
+ }
}
}
@@ -2023,6 +2049,7 @@
ConversionRestrictionKind::ValueToOptional);
}
}
+
}
// A value of type T! can be (unsafely) forced to U if T
diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp
index 88689f6..11e677a 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -1246,7 +1246,7 @@
++cs.solverState->NumTypeVariablesBound;
// If we've already explored a lot of potential solutions, bail.
- if (cs.getExpressionTooComplex())
+ if (cs.getExpressionTooComplex(solutions))
return true;
for (unsigned tryCount = 0; !anySolved && !bindings.empty(); ++tryCount) {
@@ -1951,7 +1951,7 @@
// had found at least one solution before deciding an expression was
// "too complex". Maintain that behavior, but for Swift > 3 return
// Unsolved in these cases.
- auto tooComplex = getExpressionTooComplex() &&
+ auto tooComplex = getExpressionTooComplex(solutions) &&
!getASTContext().isSwiftVersion3();
auto unsolved = tooComplex || solutions.empty();
@@ -2413,7 +2413,7 @@
break;
// If the expression was deemed "too complex", stop now and salvage.
- if (getExpressionTooComplex())
+ if (getExpressionTooComplex(solutions))
break;
// Try to solve the system with this option in the disjunction.
@@ -2465,17 +2465,6 @@
if (*restriction == ConversionRestrictionKind::TupleToTuple)
break;
}
-
- // Or, if we see a conversion successfully applied to a string
- // interpolation argument, we're done.
- // FIXME: Probably should be more general, as mentioned above.
- if (auto locator = disjunction->getLocator()) {
- if (!locator->getPath().empty() &&
- locator->getPath().back().getKind()
- == ConstraintLocator::InterpolationArgument &&
- constraint->getKind() == ConstraintKind::Conversion)
- break;
- }
}
if (TC.getLangOpts().DebugConstraintSolver) {
@@ -2492,7 +2481,7 @@
// not allow our caller to continue as if we have been successful.
// Maintain the broken behavior under Swift 3 mode though, to avoid
// breaking code.
- auto tooComplex = getExpressionTooComplex() &&
+ auto tooComplex = getExpressionTooComplex(solutions) &&
!getASTContext().isSwiftVersion3();
return tooComplex || !firstSolvedConstraint;
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index fcc284b..9ff6f65 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -814,6 +814,20 @@
storage->getSetter());
storage->setMaterializeForSetFunc(materializeForSet);
+ // Make sure we record the override.
+ //
+ // FIXME: Instead, we should just not call checkOverrides() on
+ // storage until all accessors are in place.
+ if (auto *baseASD = storage->getOverriddenDecl()) {
+ // If the base storage has a private setter, we're not overriding
+ // materializeForSet either.
+ auto *baseMFS = baseASD->getMaterializeForSetFunc();
+ if (baseMFS != nullptr &&
+ baseASD->isSetterAccessibleFrom(storage->getDeclContext())) {
+ materializeForSet->setOverriddenDecl(baseMFS);
+ }
+ }
+
return materializeForSet;
}
diff --git a/lib/Sema/ConstraintLocator.cpp b/lib/Sema/ConstraintLocator.cpp
index 924a9c8..e96e2e4 100644
--- a/lib/Sema/ConstraintLocator.cpp
+++ b/lib/Sema/ConstraintLocator.cpp
@@ -70,7 +70,6 @@
case ScalarToTuple:
case Load:
case GenericArgument:
- case InterpolationArgument:
case NamedTupleElement:
case TupleElement:
case ApplyArgToParam:
@@ -164,10 +163,6 @@
out << "instance type";
break;
- case InterpolationArgument:
- out << "interpolation argument #" << llvm::utostr(elt.getValue());
- break;
-
case Load:
out << "load";
break;
diff --git a/lib/Sema/ConstraintLocator.h b/lib/Sema/ConstraintLocator.h
index 3dd72f2..411c44e 100644
--- a/lib/Sema/ConstraintLocator.h
+++ b/lib/Sema/ConstraintLocator.h
@@ -91,8 +91,6 @@
SubscriptIndex,
/// \brief The result of a subscript expression.
SubscriptResult,
- /// \brief An argument to string interpolation.
- InterpolationArgument,
/// \brief The lookup for a constructor member.
ConstructorMember,
/// \brief Rvalue adjustment.
@@ -155,7 +153,6 @@
return 0;
case GenericArgument:
- case InterpolationArgument:
case NamedTupleElement:
case TupleElement:
return 1;
@@ -204,7 +201,6 @@
case Archetype:
case AssociatedType:
case GenericArgument:
- case InterpolationArgument:
case NamedTupleElement:
case TupleElement:
case Requirement:
@@ -335,12 +331,6 @@
return PathElement(GenericArgument, position);
}
- /// \brief Retrieve a path element for an argument to string
- /// interpolation.
- static PathElement getInterpolationArgument(unsigned position) {
- return PathElement(InterpolationArgument, position);
- }
-
/// \brief Retrieve the kind of path element.
PathElementKind getKind() const {
switch (static_cast<StoredKind>(storedKind)) {
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 7398757..cbff664 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -1570,6 +1570,10 @@
if (newBase.getPointer() == depMemTy->getBase().getPointer())
return type;
+ // Dependent member types should only be created for associated types.
+ auto assocType = depMemTy->getAssocType();
+ assert(depMemTy->getAssocType());
+
Type lookupBaseType = newBase->getLValueOrInOutObjectType();
// If the new base is still something we can't handle, just build a
@@ -1582,10 +1586,6 @@
return DependentMemberType::get(newBase, assocType);
}
- // Dependent member types should only be created for associated types.
- auto assocType = depMemTy->getAssocType();
- assert(depMemTy->getAssocType());
-
if (!lookupBaseType->mayHaveMembers()) return type;
auto result = assocType->getDeclaredInterfaceType()
@@ -1593,10 +1593,34 @@
lookupBaseType->getContextSubstitutions(
assocType->getDeclContext()));
- // FIXME: Record failure somehow?
- if (!result) return type;
+ if (result)
+ return result;
- return result;
+ // FIXME: Record failure somehow?
+ if (!lookupBaseType->getImplicitlyUnwrappedOptionalObjectType())
+ return type;
+
+ // "Force" the IUO for substitution purposes. We can end up in
+ // this situation if we use the results of overload resolution
+ // as a generic type and the overload resolution resulted in an
+ // IUO-typed entity.
+ while (auto objectType =
+ lookupBaseType->getImplicitlyUnwrappedOptionalObjectType()) {
+ lookupBaseType = objectType;
+ }
+
+ if (!lookupBaseType->mayHaveMembers()) return type;
+
+ result = assocType->getDeclaredInterfaceType()
+ .subst(DC->getParentModule(),
+ lookupBaseType->getContextSubstitutions(
+ assocType->getDeclContext()));
+
+ if (result)
+ return result;
+
+ // FIXME: Record failure somehow?
+ return type;
}
// If this is a FunctionType and we inferred new function attributes, apply
@@ -1677,3 +1701,16 @@
return type;
});
}
+
+size_t Solution::getTotalMemory() const {
+ return sizeof(*this) +
+ typeBindings.getMemorySize() +
+ overloadChoices.getMemorySize() +
+ ConstraintRestrictions.getMemorySize() +
+ llvm::capacity_in_bytes(Fixes) +
+ DisjunctionChoices.getMemorySize() +
+ OpenedTypes.getMemorySize() +
+ OpenedExistentialTypes.getMemorySize() +
+ (DefaultedConstraints.size() * sizeof(void*));
+}
+
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 4af6d62..74bc0db 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -406,8 +406,10 @@
SK_ScalarPointerConversion,
/// A conversion from an array to a pointer of matching element type.
SK_ArrayPointerConversion,
+ /// A conversion to an empty existential type ('Any' or '{}').
+ SK_EmptyExistentialConversion,
- SK_LastScoreKind = SK_ArrayPointerConversion,
+ SK_LastScoreKind = SK_EmptyExistentialConversion,
};
/// The number of score kinds.
@@ -518,6 +520,8 @@
Solution(Solution &&other) = default;
Solution &operator=(Solution &&other) = default;
+ size_t getTotalMemory() const;
+
/// \brief Retrieve the constraint system that this solution solves.
ConstraintSystem &getConstraintSystem() const { return *constraintSystem; }
@@ -880,6 +884,10 @@
/// or explore an option in a disjuction.
unsigned CountScopes = 0;
+ /// High-water mark of measured memory usage in any sub-scope we
+ /// explored.
+ size_t MaxMemory = 0;
+
/// \brief Cached member lookups.
llvm::DenseMap<std::pair<Type, DeclName>, Optional<LookupResult>>
MemberLookups;
@@ -2478,7 +2486,7 @@
/// \brief Determine if we've already explored too many paths in an
/// attempt to solve this expression.
- bool getExpressionTooComplex() {
+ bool getExpressionTooComplex(SmallVectorImpl<Solution> const &solutions) {
if (!getASTContext().isSwiftVersion3()) {
if (CountScopes < TypeCounter)
return false;
@@ -2499,8 +2507,12 @@
}
auto used = TC.Context.getSolverMemory();
+ for (auto const& s : solutions) {
+ used += s.getTotalMemory();
+ }
+ MaxMemory = std::max(used, MaxMemory);
auto threshold = TC.Context.LangOpts.SolverMemoryThreshold;
- return used > threshold;
+ return MaxMemory > threshold;
}
LLVM_ATTRIBUTE_DEPRECATED(
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index 958d9b7..28e59a6 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -3548,7 +3548,7 @@
// Always look at the parameters in the last parameter list.
for (auto param : *afd->getParameterLists().back()) {
- paramTypes.push_back(getTypeNameForOmission(param->getType())
+ paramTypes.push_back(getTypeNameForOmission(param->getInterfaceType())
.withDefaultArgument(param->isDefaultArgument()));
}
@@ -3616,10 +3616,10 @@
Optional<Identifier> TypeChecker::omitNeedlessWords(VarDecl *var) {
auto &Context = var->getASTContext();
- if (!var->hasType())
+ if (!var->hasInterfaceType())
validateDecl(var);
- if (var->isInvalid() || !var->hasType())
+ if (var->isInvalid() || !var->hasInterfaceType())
return None;
if (var->getName().empty())
@@ -3650,7 +3650,7 @@
// Omit needless words.
StringScratchSpace scratch;
- OmissionTypeName typeName = getTypeNameForOmission(var->getType());
+ OmissionTypeName typeName = getTypeNameForOmission(var->getInterfaceType());
OmissionTypeName contextTypeName = getTypeNameForOmission(contextType);
if (::omitNeedlessWords(name, { }, "", typeName, contextTypeName, { },
/*returnsSelf=*/false, true, allPropertyNames,
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index a456484..35c2a21 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -26,6 +26,7 @@
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/Decl.h"
#include "swift/AST/GenericEnvironment.h"
+#include "swift/AST/GenericSignature.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/ReferencedNameTracker.h"
#include "swift/AST/TypeMatcher.h"
@@ -2968,7 +2969,56 @@
ConformanceChecker::inferTypeWitnessesViaValueWitnesses(ValueDecl *req) {
InferredAssociatedTypesByWitnesses result;
+ auto isExtensionUsableForInference = [&](ExtensionDecl *extension) -> bool {
+ // Assume unconstrained concrete extensions we found witnesses in are
+ // always viable.
+ if (!extension->getExtendedType()->isAnyExistentialType()) {
+ // TODO: When constrained extensions are a thing, we'll need an "is
+ // as specialized as" kind of check here.
+ return !extension->isConstrainedExtension();
+ }
+
+ // The extension may not have a generic signature set up yet, as a
+ // recursion breaker, in which case we can't yet confidently reject its
+ // witnesses.
+ if (!extension->getGenericSignature())
+ return true;
+
+ // The condition here is a bit more fickle than
+ // `isProtocolExtensionUsable`. That check would prematurely reject
+ // extensions like `P where AssocType == T` if we're relying on a
+ // default implementation inside the extension to infer `AssocType == T`
+ // in the first place. Only check conformances on the `Self` type,
+ // because those have to be explicitly declared on the type somewhere
+ // so won't be affected by whatever answer inference comes up with.
+ auto selfTy = GenericTypeParamType::get(0, 0, TC.Context);
+ for (const Requirement &reqt
+ : extension->getGenericSignature()->getRequirements()) {
+ switch (reqt.getKind()) {
+ case RequirementKind::Conformance:
+ case RequirementKind::Superclass:
+ if (selfTy->isEqual(reqt.getFirstType())
+ && !TC.isSubtypeOf(Conformance->getType(),reqt.getSecondType(), DC))
+ return false;
+ break;
+
+ case RequirementKind::Layout:
+ case RequirementKind::SameType:
+ break;
+ }
+ }
+
+ return true;
+ };
+
for (auto witness : lookupValueWitnesses(req, /*ignoringNames=*/nullptr)) {
+ // If the potential witness came from an extension, and our `Self`
+ // type can't use it regardless of what associated types we end up
+ // inferring, skip the witness.
+ if (auto extension = dyn_cast<ExtensionDecl>(witness->getDeclContext()))
+ if (!isExtensionUsableForInference(extension))
+ continue;
+
// Try to resolve the type witness via this value witness.
auto witnessResult = inferTypeWitnessesViaValueWitness(req, witness);
@@ -3275,6 +3325,28 @@
/// The number of value witnesses that occur in protocol
/// extensions.
unsigned NumValueWitnessesInProtocolExtensions;
+
+#ifndef NDEBUG
+ LLVM_ATTRIBUTE_USED
+#endif
+ void dump() {
+ llvm::errs() << "Type Witnesses:\n";
+ for (auto &typeWitness : TypeWitnesses) {
+ llvm::errs() << " " << typeWitness.first->getName() << " := ";
+ typeWitness.second.first->print(llvm::errs());
+ llvm::errs() << " value " << typeWitness.second.second << '\n';
+ }
+ llvm::errs() << "Value Witnesses:\n";
+ for (unsigned i : indices(ValueWitnesses)) {
+ auto &valueWitness = ValueWitnesses[i];
+ llvm::errs() << i << ": " << (Decl*)valueWitness.first
+ << ' ' << valueWitness.first->getName() << '\n';
+ valueWitness.first->getDeclContext()->dumpContext();
+ llvm::errs() << " for " << (Decl*)valueWitness.second
+ << ' ' << valueWitness.second->getName() << '\n';
+ valueWitness.second->getDeclContext()->dumpContext();
+ }
+ }
};
/// A failed type witness binding.
@@ -3319,6 +3391,156 @@
};
} // end anonymous namespace
+static Comparison
+compareDeclsForInference(TypeChecker &TC, DeclContext *DC,
+ ValueDecl *decl1, ValueDecl *decl2) {
+ // TC.compareDeclarations assumes that it's comparing two decls that
+ // apply equally well to a call site. We haven't yet inferred the
+ // associated types for a type, so the ranking algorithm used by
+ // compareDeclarations to score protocol extensions is inappropriate,
+ // since we may have potential witnesses from extensions with mutually
+ // exclusive associated type constraints, and compareDeclarations will
+ // consider these unordered since neither extension's generic signature
+ // is a superset of the other.
+
+ // If the witnesses come from the same decl context, score normally.
+ auto dc1 = decl1->getDeclContext();
+ auto dc2 = decl2->getDeclContext();
+
+ if (dc1 == dc2)
+ return TC.compareDeclarations(DC, decl1, decl2);
+
+ auto isProtocolExt1 =
+ (bool)dc1->getAsProtocolExtensionContext();
+ auto isProtocolExt2 =
+ (bool)dc2->getAsProtocolExtensionContext();
+
+ // If one witness comes from a protocol extension, favor the one
+ // from a concrete context.
+ if (isProtocolExt1 != isProtocolExt2) {
+ return isProtocolExt1 ? Comparison::Worse : Comparison::Better;
+ }
+
+ // If both witnesses came from concrete contexts, score normally.
+ // Associated type inference shouldn't impact the result.
+ // FIXME: It could, if someone constrained to ConcreteType.AssocType...
+ if (!isProtocolExt1)
+ return TC.compareDeclarations(DC, decl1, decl2);
+
+ // Compare protocol extensions by which protocols they require Self to
+ // conform to. If one extension requires a superset of the other's
+ // constraints, it wins.
+ auto sig1 = dc1->getGenericSignatureOfContext();
+ auto sig2 = dc2->getGenericSignatureOfContext();
+
+ // FIXME: Extensions sometimes have null generic signatures while
+ // checking the standard library...
+ if (!sig1 || !sig2)
+ return TC.compareDeclarations(DC, decl1, decl2);
+
+ auto selfParam = GenericTypeParamType::get(0, 0, TC.Context);
+
+ // Collect the protocols required by extension 1.
+ Type class1;
+ SmallPtrSet<ProtocolDecl*, 4> protos1;
+
+ std::function<void (ProtocolDecl*)> insertProtocol;
+ insertProtocol = [&](ProtocolDecl *p) {
+ if (!protos1.insert(p).second)
+ return;
+
+ for (auto parent : p->getInheritedProtocols(&TC))
+ insertProtocol(parent);
+ };
+
+ for (auto &reqt : sig1->getRequirements()) {
+ if (!reqt.getFirstType()->isEqual(selfParam))
+ continue;
+ switch (reqt.getKind()) {
+ case RequirementKind::Conformance: {
+ SmallVector<ProtocolDecl*, 4> protos;
+ reqt.getSecondType()->getAnyExistentialTypeProtocols(protos);
+
+ for (auto proto : protos) {
+ insertProtocol(proto);
+ }
+ break;
+ }
+ case RequirementKind::Superclass:
+ class1 = reqt.getSecondType();
+ break;
+
+ case RequirementKind::SameType:
+ case RequirementKind::Layout:
+ break;
+ }
+ }
+
+ // Compare with the protocols required by extension 2.
+ Type class2;
+ SmallPtrSet<ProtocolDecl*, 4> protos2;
+ bool protos2AreSubsetOf1 = true;
+ std::function<void (ProtocolDecl*)> removeProtocol;
+ removeProtocol = [&](ProtocolDecl *p) {
+ if (!protos2.insert(p).second)
+ return;
+
+ protos2AreSubsetOf1 &= protos1.erase(p);
+ for (auto parent : p->getInheritedProtocols(&TC))
+ removeProtocol(parent);
+ };
+
+ for (auto &reqt : sig2->getRequirements()) {
+ if (!reqt.getFirstType()->isEqual(selfParam))
+ continue;
+ switch (reqt.getKind()) {
+ case RequirementKind::Conformance: {
+ SmallVector<ProtocolDecl*, 4> protos;
+ reqt.getSecondType()->getAnyExistentialTypeProtocols(protos);
+
+ for (auto proto : protos) {
+ removeProtocol(proto);
+ }
+ break;
+ }
+ case RequirementKind::Superclass:
+ class2 = reqt.getSecondType();
+ break;
+
+ case RequirementKind::SameType:
+ case RequirementKind::Layout:
+ break;
+ }
+ }
+
+ auto isClassConstraintAsStrict = [&](Type t1, Type t2) -> bool {
+ if (!t1)
+ return !t2;
+
+ if (!t2)
+ return true;
+
+ return TC.isSubtypeOf(t1, t2, DC);
+ };
+
+ bool protos1AreSubsetOf2 = protos1.empty();
+ // If the second extension requires strictly more protocols than the
+ // first, it's better.
+ if (protos1AreSubsetOf2 > protos2AreSubsetOf1
+ && isClassConstraintAsStrict(class2, class1)) {
+ return Comparison::Worse;
+ // If the first extension requires strictly more protocols than the
+ // second, it's better.
+ } else if (protos2AreSubsetOf1 > protos1AreSubsetOf2
+ && isClassConstraintAsStrict(class1, class2)) {
+ return Comparison::Better;
+ }
+
+ // If they require the same set of protocols, or non-overlapping
+ // sets, judge them normally.
+ return TC.compareDeclarations(DC, decl1, decl2);
+}
+
void ConformanceChecker::resolveTypeWitnesses() {
llvm::SetVector<AssociatedTypeDecl *> unresolvedAssocTypes;
@@ -3785,7 +4007,7 @@
if (firstWitness == secondWitness)
continue;
- switch (TC.compareDeclarations(DC, firstWitness, secondWitness)) {
+ switch (compareDeclsForInference(TC, DC, firstWitness, secondWitness)) {
case Comparison::Better:
if (secondBetter)
return false;
@@ -3814,8 +4036,8 @@
if (compareSolutions(solutions[i], solutions[bestIdx]))
bestIdx = i;
}
-
- // Make sure that solution is better than any of the other solutions
+
+ // Make sure that solution is better than any of the other solutions.
bool ambiguous = false;
for (unsigned i = 1, n = solutions.size(); i != n; ++i) {
if (i != bestIdx && !compareSolutions(solutions[bestIdx], solutions[i])) {
@@ -3823,7 +4045,7 @@
break;
}
}
-
+
// If we had a best solution, keep just that solution.
if (!ambiguous) {
if (bestIdx != 0)
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 61d744a..7e1f08e 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -263,6 +263,11 @@
if (ownerDC == parentDC)
return std::make_tuple(parentDC, parentNominal, true);
+ if (isa<ExtensionDecl>(parentDC) && typeDecl == parentNominal) {
+ assert(parentDC->getParent()->isModuleScopeContext());
+ return std::make_tuple(parentDC, parentNominal, true);
+ }
+
// FIXME: Horrible hack. Don't allow us to reference a generic parameter
// from a context outside a ProtocolDecl.
if (isa<ProtocolDecl>(parentDC) && isa<GenericTypeParamDecl>(typeDecl))
@@ -2641,13 +2646,19 @@
// If this is the top level of a function input list, peel off the
// ImmediateFunctionInput marker and install a FunctionInput one instead.
- //
- // If we have a single ParenType though, don't clear these bits; we
- // still want to parse the type contained therein as if it were in
- // parameter position, meaning function types are not @escaping by
- // default.
auto elementOptions = options;
- if (!repr->isParenType()) {
+ if (repr->isParenType()) {
+ // If we have a single ParenType, don't clear the context bits; we
+ // still want to parse the type contained therein as if it were in
+ // parameter position, meaning function types are not @escaping by
+ // default. We still want to reduce `ImmediateFunctionInput` to
+ // `FunctionInput` so that e.g. ((foo: Int)) -> Int is considered a
+ // tuple argument rather than a labeled Int argument.
+ if (isImmediateFunctionInput) {
+ elementOptions -= TR_ImmediateFunctionInput;
+ elementOptions |= TR_FunctionInput;
+ }
+ } else {
elementOptions = withoutContext(elementOptions, true);
if (isImmediateFunctionInput)
elementOptions |= TR_FunctionInput;
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 0925360..6b1aa80 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -1223,7 +1223,7 @@
/// from Clang can also appear in any module.
static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
CanGenericSignature expectedGenericSig, bool isType,
- bool inProtocolExt,
+ bool inProtocolExt, bool isStatic,
Optional<swift::CtorInitializerKind> ctorInit,
SmallVectorImpl<ValueDecl *> &values) {
CanType canTy;
@@ -1238,6 +1238,8 @@
return true;
if (canTy && value->getInterfaceType()->getCanonicalType() != canTy)
return true;
+ if (value->isStatic() != isStatic)
+ return true;
// FIXME: Should be able to move a value from an extension in a derived
// module to the original definition in a base module.
if (expectedModule && !value->hasClangNode() &&
@@ -1309,10 +1311,12 @@
bool isType = (recordID == XREF_TYPE_PATH_PIECE);
bool onlyInNominal = false;
bool inProtocolExt = false;
+ bool isStatic = false;
if (isType)
XRefTypePathPieceLayout::readRecord(scratch, IID, onlyInNominal);
else
- XRefValuePathPieceLayout::readRecord(scratch, TID, IID, inProtocolExt);
+ XRefValuePathPieceLayout::readRecord(scratch, TID, IID, inProtocolExt,
+ isStatic);
Identifier name = getIdentifier(IID);
pathTrace.addValue(name);
@@ -1327,8 +1331,8 @@
M->lookupQualified(ModuleType::get(M), name,
NL_QualifiedDefault | NL_KnownNoDependency,
/*typeResolver=*/nullptr, values);
- filterValues(filterTy, nullptr, nullptr, isType, inProtocolExt, None,
- values);
+ filterValues(filterTy, nullptr, nullptr, isType, inProtocolExt, isStatic,
+ None, values);
// HACK HACK HACK: Omit-needless-words hack to try to cope with
// the "NS" prefix being added/removed. No "real" compiler mode
@@ -1484,6 +1488,7 @@
bool isType = false;
bool onlyInNominal = false;
bool inProtocolExt = false;
+ bool isStatic = false;
switch (recordID) {
case XREF_TYPE_PATH_PIECE: {
IdentifierID IID;
@@ -1495,7 +1500,8 @@
case XREF_VALUE_PATH_PIECE: {
IdentifierID IID;
- XRefValuePathPieceLayout::readRecord(scratch, TID, IID, inProtocolExt);
+ XRefValuePathPieceLayout::readRecord(scratch, TID, IID, inProtocolExt,
+ isStatic);
memberName = getIdentifier(IID);
break;
}
@@ -1534,8 +1540,8 @@
auto members = nominal->lookupDirect(memberName, onlyInNominal);
values.append(members.begin(), members.end());
- filterValues(filterTy, M, genericSig, isType, inProtocolExt, ctorInit,
- values);
+ filterValues(filterTy, M, genericSig, isType, inProtocolExt, isStatic,
+ ctorInit, values);
break;
}
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index df3a571..4de00e6 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -1622,7 +1622,8 @@
XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
addTypeRef(ty),
addIdentifierRef(SD->getName()),
- isProtocolExt);
+ isProtocolExt,
+ SD->isStatic());
break;
}
@@ -1637,7 +1638,8 @@
abbrCode = DeclTypeAbbrCodes[XRefValuePathPieceLayout::Code];
XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
addTypeRef(ty), nameID,
- isProtocolExt);
+ isProtocolExt,
+ storage->isStatic());
abbrCode =
DeclTypeAbbrCodes[XRefOperatorOrAccessorPathPieceLayout::Code];
@@ -1671,7 +1673,8 @@
XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
addTypeRef(ty),
addIdentifierRef(fn->getName()),
- isProtocolExt);
+ isProtocolExt,
+ fn->isStatic());
if (fn->isOperator()) {
// Encode the fixity as a filter on the func decls, to distinguish prefix
@@ -1752,7 +1755,8 @@
XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
addTypeRef(ty),
addIdentifierRef(val->getName()),
- isProtocolExt);
+ isProtocolExt,
+ val->isStatic());
}
/// Translate from the AST associativity enum to the Serialization enum
diff --git a/stdlib/public/SDK/Dispatch/Private.swift b/stdlib/public/SDK/Dispatch/Private.swift
index ffd5402..fe0a928 100644
--- a/stdlib/public/SDK/Dispatch/Private.swift
+++ b/stdlib/public/SDK/Dispatch/Private.swift
@@ -108,7 +108,7 @@
fatalError()
}
-@available(*, unavailable, renamed:"DispatchQueue.asynchronously(self:group:qos:flags:execute:)")
+@available(*, unavailable, renamed:"DispatchQueue.async(self:group:qos:flags:execute:)")
public func dispatch_group_async(_ group: DispatchGroup, _ queue: DispatchQueue, _ block: () -> Void)
{
fatalError()
@@ -144,7 +144,7 @@
fatalError()
}
-@available(*, unavailable, renamed:"DispatchQueue.asynchronously(self:execute:)")
+@available(*, unavailable, renamed:"DispatchQueue.async(self:execute:)")
public func dispatch_async(_ queue: DispatchQueue, _ block: () -> Void)
{
fatalError()
diff --git a/stdlib/public/SDK/Dispatch/Time.swift b/stdlib/public/SDK/Dispatch/Time.swift
index 6101bcd..6e6d625 100644
--- a/stdlib/public/SDK/Dispatch/Time.swift
+++ b/stdlib/public/SDK/Dispatch/Time.swift
@@ -111,12 +111,16 @@
}
public func +(time: DispatchTime, seconds: Double) -> DispatchTime {
- let t = __dispatch_time(time.rawValue, Int64(seconds * Double(NSEC_PER_SEC)))
+ let interval = seconds * Double(NSEC_PER_SEC)
+ let t = __dispatch_time(time.rawValue,
+ interval.isInfinite || interval.isNaN ? Int64.max : Int64(interval))
return DispatchTime(rawValue: t)
}
public func -(time: DispatchTime, seconds: Double) -> DispatchTime {
- let t = __dispatch_time(time.rawValue, Int64(-seconds * Double(NSEC_PER_SEC)))
+ let interval = -seconds * Double(NSEC_PER_SEC)
+ let t = __dispatch_time(time.rawValue,
+ interval.isInfinite || interval.isNaN ? Int64.min : Int64(interval))
return DispatchTime(rawValue: t)
}
@@ -131,11 +135,15 @@
}
public func +(time: DispatchWallTime, seconds: Double) -> DispatchWallTime {
- let t = __dispatch_time(time.rawValue, Int64(seconds * Double(NSEC_PER_SEC)))
+ let interval = seconds * Double(NSEC_PER_SEC)
+ let t = __dispatch_time(time.rawValue,
+ interval.isInfinite || interval.isNaN ? Int64.max : Int64(interval))
return DispatchWallTime(rawValue: t)
}
public func -(time: DispatchWallTime, seconds: Double) -> DispatchWallTime {
- let t = __dispatch_time(time.rawValue, Int64(-seconds * Double(NSEC_PER_SEC)))
+ let interval = -seconds * Double(NSEC_PER_SEC)
+ let t = __dispatch_time(time.rawValue,
+ interval.isInfinite || interval.isNaN ? Int64.min : Int64(interval))
return DispatchWallTime(rawValue: t)
}
diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt
index 740c637..7bcc315 100644
--- a/stdlib/public/core/CMakeLists.txt
+++ b/stdlib/public/core/CMakeLists.txt
@@ -72,7 +72,6 @@
InputStream.swift
IntegerArithmetic.swift.gyb
IntegerParsing.swift.gyb
- Integers.swift.gyb
Join.swift
LazyCollection.swift.gyb
LazySequence.swift
diff --git a/stdlib/public/core/FloatingPoint.swift.gyb b/stdlib/public/core/FloatingPoint.swift.gyb
index 2ca1103..b9d9732 100644
--- a/stdlib/public/core/FloatingPoint.swift.gyb
+++ b/stdlib/public/core/FloatingPoint.swift.gyb
@@ -167,7 +167,7 @@
/// print("Average: \(average)°F in \(validTemps.count) " +
/// "out of \(tempsFahrenheit.count) observations.")
/// // Prints "Average: 74.84°F in 5 out of 7 observations."
-public protocol FloatingPoint: Comparable, Arithmetic, AbsoluteValuable,
+public protocol FloatingPoint: Comparable, AbsoluteValuable,
SignedNumber, Strideable {
/// A type that represents any written exponent.
@@ -1952,8 +1952,8 @@
/// Returns the absolute value of `x`.
@_transparent
-public func abs<T : FloatingPoint>(_ x: T) -> T where T.Magnitude == T {
- return x.magnitude
+public func abs<T : FloatingPoint>(_ x: T) -> T {
+ return T.abs(x)
}
extension FloatingPoint {
diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index bb22661..e1589c3 100644
--- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -772,7 +772,7 @@
}
}
-extension ${Self} : Arithmetic {
+extension ${Self} {
/// The magnitude of this value.
///
/// For any value `x`, `x.magnitude.sign` is `.plus`. If `x` is not NaN,
diff --git a/stdlib/public/core/Integers.swift.gyb b/stdlib/public/core/Integers.swift.gyb
deleted file mode 100644
index b6571e1..0000000
--- a/stdlib/public/core/Integers.swift.gyb
+++ /dev/null
@@ -1,730 +0,0 @@
-//===--- Integers.swift.gyb -----------------------------------*- swift -*-===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
- %{
-#
-# Utility code for later in this template
-#
-
-from string import maketrans, capitalize
-
-# Number of bits in the Builtin.Word type
-word_bits = int(CMAKE_SIZEOF_VOID_P) * 8
-
-# Number of bits in integer literals.
-builtinIntLiteralBits = 2048
-IntLiteral = 'Int%s' % builtinIntLiteralBits
-
-class struct(object):
- def __init__(self, **kw):
- self.__dict__ = kw
- def __repr__(self):
- return 'struct(%r)' % self.__dict__
-
-binaryArithmetic = {
- 'Arithmetic' : [
- struct(operator='+', name='adding', mutatingName='add', firstArg='_', llvmName='add', kind='+'),
- struct(operator='-', name='subtracting', mutatingName='subtract', firstArg='_', llvmName='sub', kind='-'),
- struct(operator='*', name='multiplied', mutatingName='multiply', firstArg='by', llvmName='mul', kind='*'),
- struct(operator='/', name='divided', mutatingName='divide', firstArg='by', llvmName='div', kind='/'),
- ],
- 'BinaryInteger' : [
- struct(operator='%', name='remainder', mutatingName='formRemainder', firstArg='dividingBy', llvmName='rem', kind='/'),
- ],
-}
-
-binaryBitwise = [
- struct(operator='&', name='bitwiseAnd', llvmName='and'),
- struct(operator='|', name='bitwiseOr', llvmName='or'),
- struct(operator='^', name='bitwiseXor', llvmName='xor'),
-]
-
-maskingShifts = [
- struct(
- operator='&>>', nonMaskingOperator='>>', description='right shift',
- name='maskingShiftRight', llvmName=lambda s:['lshr','ashr'][s]),
- struct(
- operator='&<<', nonMaskingOperator='<<', description='left shift',
- name='maskingShiftLeft', llvmName=lambda _: 'shl'),
-]
-}%
-
-infix operator &<< : BitwiseShiftPrecedence
-infix operator &<<= : AssignmentPrecedence
-infix operator &>> : BitwiseShiftPrecedence
-infix operator &>>= : AssignmentPrecedence
-
-//===----------------------------------------------------------------------===//
-//===--- Bits for the Stdlib ----------------------------------------------===//
-//===----------------------------------------------------------------------===//
-
-
-// FIXME(integers): This should go in the stdlib separately, probably.
-extension ExpressibleByIntegerLiteral
- where Self : _ExpressibleByBuiltinIntegerLiteral {
- /// Create an instance initialized to `value`.
- @_transparent
- public init(integerLiteral value: Self) {
- self = value
- }
-}
-
-//===----------------------------------------------------------------------===//
-//===--- Arithmetic -------------------------------------------------------===//
-//===----------------------------------------------------------------------===//
-
-/// Declares methods backing binary arithmetic operators--such as `+`, `-` and
-/// `*`--and their mutating counterparts.
-///
-/// It provides a suitable basis for arithmetic on scalars such as integers and
-/// floating point numbers.
-///
-/// Both mutating and non-mutating operations are declared in the protocol,
-/// however only the mutating ones are required, as default implementations of
-/// the non-mutating ones are provided by a protocol extension.
-///
-/// The `Magnitude` associated type is able to hold the absolute value of any
-/// possible value of `Self`. Concrete types do not have to provide a typealias
-/// for it, as it can be inferred from the `magnitude` property. This property
-/// can be useful in operations that are simpler to implement in terms of
-/// unsigned values, for example, printing a value of an integer, which is just
-/// printing a '-' character in front of an absolute value.
-///
-/// Please note that for ordinary work, the `magnitude` property **should not**
-/// be preferred to the `abs(_)` function, whose return value is of the same
-/// type as its argument.
-public protocol Arithmetic : Equatable, ExpressibleByIntegerLiteral {
- // FIXME(integers): implement
- //init?<T : BinaryInteger>(exactly source: T)
-
- // FIXME(ABI)#44 (Recursive Protocol Constraints): should be just Arithmetic
- associatedtype Magnitude : Equatable, ExpressibleByIntegerLiteral
-
- var magnitude: Magnitude { get }
-
-
-% for x in binaryArithmetic['Arithmetic']:
- // defaulted using an in-place counterpart, but can be used as an
- // optimization hook
- func ${x.name}(${x.firstArg} rhs: Self) -> Self
-
- // implementation hook
- mutating func ${x.mutatingName}(${x.firstArg} rhs: Self)
-% end
-}
-
-extension Arithmetic {
- @_transparent
- public init() {
- self = 0
- }
-}
-
-% for Protocol in binaryArithmetic:
-extension ${Protocol} {
-% for x in binaryArithmetic[Protocol]:
-% callLabel = x.firstArg + ': ' if not x.firstArg == '_' else ''
- public func ${x.name}(${x.firstArg} rhs: Self) -> Self {
- var lhs = self
- lhs.${x.mutatingName}(${callLabel}rhs)
- return lhs
- }
-% end
-}
-% end
-
-public protocol SignedArithmetic : Arithmetic {
- func negated() -> Self
- mutating func negate()
-}
-
-extension SignedArithmetic {
- public func negated() -> Self {
- return Self().subtracting(self)
- }
- public mutating func negate() {
- self = negated()
- }
-}
-
-//===----------------------------------------------------------------------===//
-//===--- Arithmetic operators ---------------------------------------------===//
-//===----------------------------------------------------------------------===//
-
-% for Protocol in binaryArithmetic:
-% for x in binaryArithmetic[Protocol]:
-% callLabel = x.firstArg + ': ' if not x.firstArg == '_' else ''
-@_transparent
-public func ${x.operator} <T: ${Protocol}>(lhs: T, rhs: T) -> T {
- return lhs.${x.name}(${callLabel}rhs)
-}
-
-@_transparent
-public func ${x.operator}= <T: ${Protocol}>(lhs: inout T, rhs: T) {
- lhs.${x.mutatingName}(${callLabel}rhs)
-}
-% end
-% end
-
-@_transparent
-public prefix func - <T: SignedArithmetic>(x: T) -> T {
- return x.negated()
-}
-
-//===----------------------------------------------------------------------===//
-//===--- BinaryInteger ----------------------------------------------------===//
-//===----------------------------------------------------------------------===//
-
-public protocol BinaryInteger :
- Comparable, Arithmetic, CustomStringConvertible {
-
- static var isSigned: Bool { get }
-
- // Dispatching through these puts less stress on the user reading
- // the interface and error messages (and on the type checker) than
- // does having many operator overloads.
- func isEqual(to rhs: Self) -> Bool
- func isLess(than rhs: Self) -> Bool
-
- init?<T : FloatingPoint>(exactly source: T)
-
- init<T : FloatingPoint>(_ source: T)
-
- init<T : BinaryInteger>(_ source: T)
-
- init<T : BinaryInteger>(extendingOrTruncating source: T)
-
- init<T : BinaryInteger>(clamping source: T)
-
- func word(at n: Int) -> UInt
-
- var bitWidth : Int { get }
-
- var minimumSignedRepresentationBitWidth: Int { get }
-
-% for x in binaryArithmetic['BinaryInteger']:
- // defaulted using an in-place counterpart, but can be used as an
- // optimization hook
- func ${x.name}(${x.firstArg} rhs: Self) -> Self
-
- // implementation hook
- mutating func ${x.mutatingName}(${x.firstArg} rhs: Self)
-% end
-
- func quotientAndRemainder(dividingBy rhs: Self) -> (Self, Self)
-
- /// Returns `-1` if the value of `self` is negative, `1` if it's positive,
- /// `0` otherwise.
- func signum() -> Self
-}
-
-extension BinaryInteger {
- public init?<T : FloatingPoint>(exactly source: T) {
- // FIXME(integers): implement
- fatalError()
- return nil
- }
-
- public init<T : FloatingPoint>(_ source: T) {
- // FIXME(integers): implement
- fatalError()
- }
-
- public func signum() -> Self {
- // FIXME(integers): implement
- fatalError()
- }
-
- public var countRepresentedWords: Int {
- return (self.bitWidth + ${word_bits} - 1) / ${word_bits}
- }
-
- public func quotientAndRemainder(dividingBy rhs: Self) -> (Self, Self) {
- return (self.divided(by: rhs), self.remainder(dividingBy: rhs))
- }
-}
-
-//===----------------------------------------------------------------------===//
-//===--- Homogeneous comparison -------------------------------------------===//
-//===----------------------------------------------------------------------===//
-
-@_transparent
-public func == <T : BinaryInteger>(lhs: T, rhs: T) -> Bool {
- return lhs.isEqual(to: rhs)
-}
-
-@_transparent
-public func < <T : BinaryInteger>(lhs: T, rhs: T) -> Bool {
- return lhs.isLess(than: rhs)
-}
-
-//===----------------------------------------------------------------------===//
-//===--- Heterogeneous comparison -----------------------------------------===//
-//===----------------------------------------------------------------------===//
-
-@_transparent
-public func == <T : BinaryInteger, U : BinaryInteger>(lhs: T, rhs: U) -> Bool {
- return (lhs > 0) == (rhs > 0)
- && T(extendingOrTruncating: rhs) == lhs
- && U(extendingOrTruncating: lhs) == rhs
-}
-
-@_transparent
-public func != <T : BinaryInteger, U : BinaryInteger>(lhs:T, rhs: U) -> Bool {
- return !(lhs == rhs)
-}
-
-@_transparent
-public func < <T : BinaryInteger, U : BinaryInteger>(lhs: T, rhs: U) -> Bool {
- let lhsSign = lhs < 0 ? -1 : lhs > 0 ? 1 : 0
- let rhsSign = rhs < 0 ? -1 : rhs > 0 ? 1 : 0
- if lhsSign != rhsSign { return lhsSign < rhsSign }
-
- // if we get here, lhs and rhs have the same sign. If they're
- // negative, then T and U are both signed types, and one of them can
- // represent values of the other type. Otherwise, lhs and rhs are
- // positive, and one of T, U may be signed and the other unsigned.
- // In this case, we can conceptually subtract 1 from the bitWidth of
- // any signed type, and either the resulting bitWidths are the same
- // or one can represent every value of the other.
-
- let rT = T(extendingOrTruncating: rhs)
-
- // Can we round-trip rhs through T?
- if U(extendingOrTruncating: rT) == rhs {
- return lhs < rT
- }
-
- return U(extendingOrTruncating: lhs) < rhs
-}
-
-@inline(__always)
-public func <= <T : BinaryInteger, U : BinaryInteger>(lhs: T, rhs: U) -> Bool {
- return !(rhs < lhs)
-}
-
-@inline(__always)
-public func >= <T : BinaryInteger, U : BinaryInteger>(lhs: T, rhs: U) -> Bool {
- return !(lhs < rhs)
-}
-
-@inline(__always)
-public func > <T : BinaryInteger, U : BinaryInteger>(lhs: T, rhs: U) -> Bool {
- return rhs < lhs
-}
-
-//===----------------------------------------------------------------------===//
-//===--- Ambiguity breakers -----------------------------------------------===//
-// These two versions of the operators are not ordered with respect to
-// one another:
-//
-// <T : Comparable>(T, T) -> Bool
-// <T : BinaryInteger, U : BinaryInteger>(T, U) -> Bool
-//
-// so we define:
-//
-// <T : BinaryInteger>(T, T) -> Bool
-//===----------------------------------------------------------------------===//
-
-@_transparent
-public func != <T : BinaryInteger>(lhs: T, rhs: T) -> Bool {
- return !(lhs == rhs)
-}
-
-@inline(__always)
-public func <= <T : BinaryInteger>(lhs: T, rhs: T) -> Bool {
- return !(rhs < lhs)
-}
-
-@inline(__always)
-public func >= <T : BinaryInteger>(lhs: T, rhs: T) -> Bool {
- return !(lhs < rhs)
-}
-
-@inline(__always)
-public func > <T : BinaryInteger>(lhs: T, rhs: T) -> Bool {
- return rhs < lhs
-}
-
-//===----------------------------------------------------------------------===//
-//===--- FixedWidthInteger ------------------------------------------------===//
-//===----------------------------------------------------------------------===//
-
-public enum ArithmeticOverflow {
- @_transparent
- public init(_ overflow: Bool) { self = overflow ? .overflow : .none }
- case none, overflow
-}
-
-public protocol FixedWidthInteger : BinaryInteger {
- static var bitWidth : Int { get }
-
- static var max: Self { get }
- static var min: Self { get }
-
-% for x in binaryArithmetic['Arithmetic']:
-%{
-comment = '''
- /// Return a pair consisting of `self` {} `rhs`,
- /// truncated to fit if necessary, and a flag indicating whether an
- /// arithmetic overflow occurred.'''.format(x.operator) + ('''
- ///
- /// - Precondition: `rhs != 0`''' if x.kind == '/' else '')
-}%
-${comment}
- func ${x.name}WithOverflow(
- ${x.firstArg} rhs: Self
- ) -> (partialValue: Self, overflow: ArithmeticOverflow)
-% end
-
-% for x in binaryBitwise + maskingShifts:
- func ${x.name}(_ rhs: Self) -> Self
-% end
-
- static func doubleWidthMultiply(_ lhs: Self, _ rhs: Self)
- -> (high: Self, low: Magnitude)
- static func doubleWidthDivide(
- _ lhs: (high: Self, low: Magnitude), _ rhs: Self)
- -> (quotient: Self, remainder: Self)
-
- init(_truncatingBits bits: UInt)
-
- var popcount: Int { get }
- var leadingZeros: Int { get }
-}
-
-//===----------------------------------------------------------------------===//
-//===--- Operators on FixedWidthInteger -----------------------------------===//
-//===----------------------------------------------------------------------===//
-
-@inline(__always)
-public prefix func ~ <T: FixedWidthInteger>(x: T) -> T {
- return 0 &- x &- 1
-}
-
-% for x in binaryBitwise:
-@_transparent
-public func ${x.operator} <T: FixedWidthInteger>(lhs: T, rhs: T) -> T {
- return lhs.${x.name}(rhs)
-}
-
-@_transparent
-public func ${x.operator}= <T: FixedWidthInteger>(lhs: inout T, rhs: T) {
- lhs = lhs.${x.name}(rhs)
-}
-% end
-
-% for x in maskingShifts:
-
-@_transparent
-public func ${x.operator} <T: FixedWidthInteger>(lhs: T, rhs: T) -> T {
- return lhs.${x.name}(rhs)
-}
-
-@_transparent
-public func ${x.operator}= <T: FixedWidthInteger>(lhs: inout T, rhs: T) {
- lhs = lhs ${x.operator} rhs
-}
-
-@_transparent
-public func ${x.operator} <
- T: FixedWidthInteger, U: BinaryInteger
->(lhs: T, rhs: U) -> T {
- return lhs.${x.name}(T(extendingOrTruncating: rhs))
-}
-
-@_transparent
-public func ${x.operator}= <
- T: FixedWidthInteger, U: BinaryInteger
->(lhs: inout T, rhs: U) {
- lhs = lhs ${x.operator} rhs
-}
-
-@_transparent
-public func ${x.nonMaskingOperator} <
- T: FixedWidthInteger, U: BinaryInteger
->(lhs: T, rhs: U) -> T {
- // FIXME(integers): uncomment once Int conforms to BinaryInteger
- //let shift = rhs < -T.bitWidth ? -T.bitWidth
- //: rhs > T.bitWidth ? T.bitWidth
- //: Int(rhs)
- //return lhs ${x.nonMaskingOperator} shift
- fatalError()
-}
-
-//===----------------------------------------------------------------------===//
-//=== "Smart ${x.description}", supporting overshifts and negative shifts -===//
-//===----------------------------------------------------------------------===//
-
-@_transparent
-public func ${x.nonMaskingOperator} <
- T: FixedWidthInteger
->(lhs: T, rhs: Int) -> T {
- // FIXME(integers): uncomment once Int conforms to BinaryInteger
- fatalError()
- //let overshiftR = T.isSigned ? lhs &>> (T.bitWidth - 1) : 0
- //let overshiftL: T = 0
- //if _fastPath(rhs >= 0) {
- //if _fastPath(rhs < T.bitWidth) {
- //return lhs.${x.name}(T(extendingOrTruncating: rhs))
- //}
- //return overshift${'LR'['R' in x.name]}
- //}
-
- //if _slowPath(rhs <= -T.bitWidth) {
- //return overshift${'RL'['R' in x.name]}
- //}
- //return lhs ${x.operator.translate(maketrans('<>', '><'))} -rhs
-}
-
-@_transparent
-public func ${x.nonMaskingOperator}= <
- T: FixedWidthInteger
->(lhs: inout T, rhs: T) {
- lhs = lhs ${x.nonMaskingOperator} rhs
-}
-
-@_transparent
-public func ${x.nonMaskingOperator}= <
- T: FixedWidthInteger, U: BinaryInteger
->(lhs: inout T, rhs: U) {
- lhs = lhs ${x.nonMaskingOperator} rhs
-}
-
-% end # maskingShifts
-
-
-extension FixedWidthInteger {
- public init<Other: BinaryInteger>(clamping source: Other) {
- if _slowPath(source < Self.min) {
- self = Self.min
- }
- else if _slowPath(source > Self.max) {
- self = Self.max
- }
- else { self = Self(extendingOrTruncating: source) }
- }
-
-% for x in binaryArithmetic['Arithmetic']:
-% callLabel = x.firstArg + ': ' if not x.firstArg == '_' else ''
- @_transparent
- // FIXME(integers): rename `rhs` to `other`
- public mutating func ${x.mutatingName}(${x.firstArg} rhs: Self) {
- let (result, _ /*overflow*/) = self.${x.name}WithOverflow(${callLabel}rhs)
- // FIXME(integers): overflow check
- //_assertCond(overflow == .none, "overflow in ${x.name}")
- self = result
- }
-
- /// Return `self ${x.operator} rhs`. If an arithmetic overflow
- /// occurs, the behavior is undefined.
- ///
- /// Note: use this function to avoid the cost of overflow checking
- /// when you are sure that the operation won't overflow.
- @_transparent
- public func unsafe${capitalize(x.name)}(rhs: Self) -> Self {
- let (result, overflow) = self.${x.name}WithOverflow(${callLabel}rhs)
-
- if (overflow != .none) {
- if (_isDebugAssertConfiguration()) {
- _preconditionFailure("overflow in unsafe${capitalize(x.name)}")
- }
- else {
- Builtin.conditionallyUnreachable()
- }
- }
- return result
- }
-% end
-
- @_transparent
- public mutating func formRemainder(dividingBy other: Self) {
- // FIXME(integers): implement
- fatalError()
- }
-
- @_transparent
- public init<T : BinaryInteger>(extendingOrTruncating source: T) {
- if Self.bitWidth <= ${word_bits} {
- self = Self.init(_truncatingBits: source.word(at: 0))
- }
- else {
- var result: Self = source < 0 ? ~0 : 0
- // start with the most significant word
- var n = source.countRepresentedWords
- while n >= 0 {
- // masking is OK here because this we have already ensured
- // that Self.bitWidth > ${word_bits}. Not masking results in
- // infinite recursion.
- result &<<= ${word_bits}
- result |= Self(_truncatingBits: source.word(at: n))
- n -= 1
- }
-
- self = result
- }
- }
-
- @_transparent
- // FIXME(integers): give it a better name. _highBitIndex is **NOT** what it is
- public // transparent
- static var _highBitIndex: Self {
- // FIXME(integers): uncomment once UInt conforms to BinaryInteger
- //return Self.init(_truncatingBits: UInt(Self.bitWidth._storage) &- 1)
- fatalError()
- }
-
- public var popcount: Int {
- fatalError()
- }
-
- public static func doubleWidthDivide(
- _ lhs: (high: Self, low: Magnitude), _ rhs: Self)
- -> (quotient: Self, remainder: Self) {
- fatalError()
- }
-}
-
-% for x in [op for ops in binaryArithmetic.values() for op in ops]:
-% callLabel = x.firstArg + ': ' if not x.firstArg == '_' else ''
-% if x.kind != '/':
-public func &${x.operator} <T: FixedWidthInteger>(lhs: T, rhs: T) -> T {
- return lhs.${x.name}WithOverflow(${callLabel}rhs).partialValue
-}
-% end
-% end
-
-//===----------------------------------------------------------------------===//
-//===--- UnsignedInteger --------------------------------------------------===//
-//===----------------------------------------------------------------------===//
-
-public protocol UnsignedInteger_ : BinaryInteger {
- associatedtype Magnitude : BinaryInteger
-}
-
-extension UnsignedInteger_ {
- @_transparent
- public var magnitude: Self { return self }
-
- @_transparent
- public static var isSigned: Bool { return false }
-
- public var description: String {
- // FIXME(integers): uncomment once Int conforms to BinaryInteger
- fatalError()
- //if self == 0 {
- //return "0"
- //}
-
- //let ascii0 = 48
- //var buf: [UnicodeScalar] = []
-
- //var x = self
- //repeat {
- //let r = x % 10
- //x /= 10
- //buf.append(
- //UnicodeScalar(
- //ascii0 + Int(Word(extendingOrTruncating: r)._storage)))
- //}
- //while x != 0
- //return String(buf.reversed().lazy.map { Character($0) })
- }
-}
-
-extension UnsignedInteger_ where Self : FixedWidthInteger {
- @_transparent
- public init<T : BinaryInteger>(_ source: T) {
- // FIXME(integers): uncomment checks
- //_assertCond(
- //source >= 0, "negative value \(source) not representable by \(Self.self)")
- //let requiredBits = source.minimumSignedRepresentationBitWidth - 1
- //_assertCond(
- //requiredBits <= Self.bitWidth,
- //"\(Self.self) cannot store all \(requiredBits) bits "
- //+ "needed for unsigned representation of \(source)")
- self.init(extendingOrTruncating: source)
- }
-
- @_transparent
- public init?<T : BinaryInteger>(exactly source: T) {
- // FIXME(integers): uncomment checks
- //_assertCond(
- //source >= 0, "negative value \(source) not representable by \(Self.self)")
- let requiredBits = source.minimumSignedRepresentationBitWidth - 1
- if requiredBits > Self.bitWidth {
- return nil
- }
- self.init(extendingOrTruncating: source)
- }
-
- @_transparent
- public static var max: Self {
- return ~0
- }
-
- @_transparent
- public static var min: Self {
- return 0
- }
-
-}
-
-
-//===----------------------------------------------------------------------===//
-//===--- SignedInteger ----------------------------------------------------===//
-//===----------------------------------------------------------------------===//
-
-public protocol SignedInteger_ : BinaryInteger, SignedArithmetic {
- associatedtype Magnitude : BinaryInteger
-}
-
-extension SignedInteger_ {
- public var description: String {
- let base = String(describing: magnitude)
- return self < 0 ? "-" + base : base
- }
-
- @_transparent
- public static var isSigned: Bool { return true }
-}
-
-extension SignedInteger_ where Self : FixedWidthInteger {
- @_transparent
- public init<T : BinaryInteger>(_ source: T) {
- // FIXME(integers): uncomment checks
- //let requiredBits = source.minimumSignedRepresentationBitWidth
- //_assertCond(
- //requiredBits <= Self.bitWidth,
- //"\(Self.self) cannot store all \(requiredBits) bits "
- //+ "needed for signed representation of \(source)")
- self.init(extendingOrTruncating: source)
- }
-
- @_transparent
- public init?<T : BinaryInteger>(exactly source: T) {
- let requiredBits = source.minimumSignedRepresentationBitWidth
- if requiredBits > Self.bitWidth {
- return nil
- }
- self.init(extendingOrTruncating: source)
- }
-
- @_transparent
- public static var max: Self {
- return ~min
- }
-
- @_transparent
- public static var min: Self {
- return -1 &<< Self._highBitIndex
- }
-}
diff --git a/stdlib/public/core/MutableCollection.swift b/stdlib/public/core/MutableCollection.swift
index 0acea74..df5b7b7 100644
--- a/stdlib/public/core/MutableCollection.swift
+++ b/stdlib/public/core/MutableCollection.swift
@@ -372,6 +372,30 @@
}
}
+extension MutableCollection where Self: BidirectionalCollection {
+ public subscript(bounds: Range<Index>) -> MutableBidirectionalSlice<Self> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return MutableBidirectionalSlice(base: self, bounds: bounds)
+ }
+ set {
+ _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+ }
+ }
+}
+
+extension MutableCollection where Self: RandomAccessCollection {
+ public subscript(bounds: Range<Index>) -> MutableRandomAccessSlice<Self> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return MutableRandomAccessSlice(base: self, bounds: bounds)
+ }
+ set {
+ _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+ }
+ }
+}
+
@available(*, unavailable, renamed: "MutableCollection")
public typealias MutableCollectionType = MutableCollection
diff --git a/stdlib/public/core/RangeReplaceableCollection.swift.gyb b/stdlib/public/core/RangeReplaceableCollection.swift.gyb
index b91f909..db2461f 100644
--- a/stdlib/public/core/RangeReplaceableCollection.swift.gyb
+++ b/stdlib/public/core/RangeReplaceableCollection.swift.gyb
@@ -793,6 +793,43 @@
public mutating func reserveCapacity(_ n: IndexDistance) {}
}
+// Offer the most specific slice type available for each possible combination of
+// RangeReplaceable * (1 + Bidirectional + RandomAccess) * (1 + Mutable)
+// collections.
+
+% for capability in ['', 'Bidirectional', 'RandomAccess']:
+% if capability:
+extension RangeReplaceableCollection where
+ Self: ${capability}Collection,
+ Self.SubSequence == RangeReplaceable${capability}Slice<Self> {
+ public subscript(bounds: Range<Index>)
+ -> RangeReplaceable${capability}Slice<Self> {
+ return RangeReplaceable${capability}Slice(base: self, bounds: bounds)
+ }
+}
+% end
+
+extension RangeReplaceableCollection where
+ Self: MutableCollection,
+% if capability:
+ Self: ${capability}Collection,
+% end
+ Self.SubSequence == MutableRangeReplaceable${capability}Slice<Self>
+{
+ public subscript(bounds: Range<Index>)
+ -> MutableRangeReplaceable${capability}Slice<Self> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return MutableRangeReplaceable${capability}Slice(base: self,
+ bounds: bounds)
+ }
+ set {
+ _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+ }
+ }
+}
+% end
+
extension RangeReplaceableCollection where SubSequence == Self {
/// Removes and returns the first element of the collection.
///
diff --git a/stdlib/public/core/StringInterpolation.swift.gyb b/stdlib/public/core/StringInterpolation.swift.gyb
index b8062a1..e54aeb8 100644
--- a/stdlib/public/core/StringInterpolation.swift.gyb
+++ b/stdlib/public/core/StringInterpolation.swift.gyb
@@ -68,29 +68,35 @@
self = String(describing: expr)
}
-% for Type in StreamableTypes:
/// Creates a string containing the given value's textual representation.
///
/// Do not call this initializer directly. It is used by the compiler when
/// interpreting string interpolations.
///
/// - SeeAlso: `ExpressibleByStringInterpolation`
- public init(stringInterpolationSegment expr: ${Type}) {
+ public init<T: TextOutputStreamable> (stringInterpolationSegment expr: T) {
self = _toStringReadOnlyStreamable(expr)
}
-% end
-% for Type in PrintableTypes:
/// Creates a string containing the given value's textual representation.
///
/// Do not call this initializer directly. It is used by the compiler when
/// interpreting string interpolations.
///
/// - SeeAlso: `ExpressibleByStringInterpolation`
- public init(stringInterpolationSegment expr: ${Type}) {
+ public init<T: CustomStringConvertible> (stringInterpolationSegment expr: T) {
self = _toStringReadOnlyPrintable(expr)
}
-% end
+
+ /// Creates a string containing the given value's textual representation.
+ ///
+ /// Do not call this initializer directly. It is used by the compiler when
+ /// interpreting string interpolations.
+ ///
+ /// - SeeAlso: `ExpressibleByStringInterpolation`
+ public init<T: TextOutputStreamable & CustomStringConvertible> (stringInterpolationSegment expr: T) {
+ self = _toStringReadOnlyStreamable(expr)
+ }
}
// ${'Local Variables'}:
diff --git a/test/ClangImporter/pch-bridging-header.swift b/test/ClangImporter/pch-bridging-header.swift
index cc92bc9..1609911 100644
--- a/test/ClangImporter/pch-bridging-header.swift
+++ b/test/ClangImporter/pch-bridging-header.swift
@@ -5,19 +5,19 @@
// RUN: %target-swift-frontend -emit-pch -o %t/sdk-bridging-header.pch %S/Inputs/sdk-bridging-header.h
// RUN: %target-swift-frontend -parse -verify %s -import-objc-header %t/sdk-bridging-header.pch
-// Now test the driver-automated version is inert when (default) disabled
-// RUN: env TMPDIR=%t/tmp/ %target-swiftc_driver -parse -save-temps %s -import-objc-header %S/Inputs/sdk-bridging-header.h
+// Now test the driver-automated version is inert when disabled
+// RUN: env TMPDIR=%t/tmp/ %target-swiftc_driver -parse -disable-bridging-pch -save-temps %s -import-objc-header %S/Inputs/sdk-bridging-header.h
// RUN: not ls %t/tmp/*.pch >/dev/null 2>&1
-// Test the driver-automated version works when enabled
-// RUN: env TMPDIR=%t/tmp/ %target-swiftc_driver -parse -save-temps %s -enable-bridging-pch -import-objc-header %S/Inputs/sdk-bridging-header.h
+// Test the driver-automated version works by default
+// RUN: env TMPDIR=%t/tmp/ %target-swiftc_driver -parse -save-temps %s -import-objc-header %S/Inputs/sdk-bridging-header.h
// RUN: ls %t/tmp/*.pch >/dev/null 2>&1
// RUN: llvm-objdump -raw-clang-ast %t/tmp/*.pch | llvm-bcanalyzer -dump | %FileCheck %s
// CHECK: ORIGINAL_FILE{{.*}}Inputs/sdk-bridging-header.h
// Test the driver-automated version deletes its PCH file when done
// RUN: rm %t/tmp/*.pch
-// RUN: env TMPDIR=%t/tmp/ %target-swiftc_driver -parse %s -enable-bridging-pch -import-objc-header %S/Inputs/sdk-bridging-header.h
+// RUN: env TMPDIR=%t/tmp/ %target-swiftc_driver -parse %s -import-objc-header %S/Inputs/sdk-bridging-header.h
// RUN: not ls %t/tmp/*.pch >/dev/null 2>&1
import Foundation
diff --git a/test/Compatibility/tuple_arguments.swift b/test/Compatibility/tuple_arguments.swift
index c4e16f8..421ed1b 100644
--- a/test/Compatibility/tuple_arguments.swift
+++ b/test/Compatibility/tuple_arguments.swift
@@ -1434,3 +1434,11 @@
block(c, c)
}
}
+
+// expected-error@+1 {{cannot create a single-element tuple with an element label}}
+func singleElementTupleArgument(completion: ((didAdjust: Bool)) -> Void) {
+ // TODO: Error could be improved.
+ // expected-error@+1 {{cannot convert value of type '(didAdjust: Bool)' to expected argument type 'Bool'}}
+ completion((didAdjust: true))
+}
+
diff --git a/test/Constraints/array_literal.swift b/test/Constraints/array_literal.swift
index 902f106..fe64443 100644
--- a/test/Constraints/array_literal.swift
+++ b/test/Constraints/array_literal.swift
@@ -227,3 +227,10 @@
}
]
)
+
+// Infer [[Int]] for SR3786aa.
+// FIXME: As noted in SR-3786, this was the behavior in Swift 3, but
+// it seems like the wrong choice and is less by design than by
+// accident.
+let SR3786a: [Int] = [1, 2, 3]
+let SR3786aa = [SR3786a.reversed(), SR3786a]
diff --git a/test/Constraints/closures.swift b/test/Constraints/closures.swift
index 250f32a..830ae64 100644
--- a/test/Constraints/closures.swift
+++ b/test/Constraints/closures.swift
@@ -437,3 +437,8 @@
func sr3497() {
let _ = sr3497_unfold((0, 0)) { s in 0 } // ok
}
+
+// SR-3758: Swift 3.1 fails to compile 3.0 code involving closures and IUOs
+let _: ((Any?) -> Void) = { (arg: Any!) in }
+// This example was rejected in 3.0 as well, but accepting it is correct.
+let _: ((Int?) -> Void) = { (arg: Int!) in }
diff --git a/test/Constraints/diag_ambiguities.swift b/test/Constraints/diag_ambiguities.swift
index 7e7a9ec..04dbf66 100644
--- a/test/Constraints/diag_ambiguities.swift
+++ b/test/Constraints/diag_ambiguities.swift
@@ -36,13 +36,9 @@
return rdar29691909_callee(o) // expected-error{{ambiguous use of 'rdar29691909_callee'}}
}
-// FIXME: The fix for this broke other things. We want to get this
-// test case running again, though.
-// Ensure that we decay Any! to Any? rather than allowing Any!-to-Any
-// conversion directly and ending up with an ambiguity here.
-//func rdar29907555(_ value: Any!) -> String {
-// return "\(value)" // no error
-//}
+func rdar29907555(_ value: Any!) -> String {
+ return "\(value)" // no error
+}
struct SR3715 {
var overloaded: Int!
diff --git a/test/Constraints/dynamic_lookup.swift b/test/Constraints/dynamic_lookup.swift
index c7b71b9..b0d08ee 100644
--- a/test/Constraints/dynamic_lookup.swift
+++ b/test/Constraints/dynamic_lookup.swift
@@ -230,3 +230,20 @@
anyDict["test"] = anyValue
_ = anyDict["test"]!.bar() // expected-error {{value of type 'Any' has no member 'bar'}}
// expected-note@-1 {{cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members}}{{5-5=(}}{{21-21= as AnyObject)}}
+
+// Test that overload resolution during constraint solving of values
+// looked-up dynamically through AnyObject are treated as conforming
+// to the protocols they are supposed to conform to.
+class NSObjDerived1 : NSObject {
+ var everything: [Any] = []
+}
+
+class NSObjDerived2 : NSObject {
+ var everything: Any = 1
+}
+
+func rdar29960565(_ o: AnyObject) {
+ for i in o.everything {
+ _ = i
+ }
+}
diff --git a/test/Constraints/interpolation_segments.swift b/test/Constraints/interpolation_segments.swift
new file mode 100644
index 0000000..8811e88
--- /dev/null
+++ b/test/Constraints/interpolation_segments.swift
@@ -0,0 +1,45 @@
+// RUN: %target-typecheck-verify-swift -typecheck -debug-constraints %s > %t.dump 2>&1
+// RUN: %FileCheck %s < %t.dump
+
+// Make sure that the interpolation segments get placed into separate connected
+// components.
+// CHECK: ---Connected components---
+// CHECK-NEXT: 0:
+// CHECK-NEXT: 1:
+// CHECK-NEXT: 2:
+// CHECK-NEXT: 3:
+// CHECK-NEXT: 4:
+// CHECK-NEXT: 5:
+// CHECK-NEXT: 6:
+// CHECK-NEXT: 7:
+// CHECK-NEXT: 8:
+// CHECK-NEXT: 9:
+
+// CHECK: (solving component #
+// CHECK: literal=3 bindings=(subtypes of) (default from ExpressibleByStringLiteral) String)
+
+// CHECK: (solving component #
+// CHECK: literal=3 bindings=(subtypes of) (default from ExpressibleByIntegerLiteral) Int)
+
+// CHECK: (solving component #
+// CHECK: literal=3 bindings=(subtypes of) (default from ExpressibleByStringLiteral) String)
+
+// CHECK: (solving component #
+// CHECK: literal=3 bindings=(subtypes of) (default from ExpressibleByIntegerLiteral) Int)
+
+// CHECK: (solving component #
+// CHECK: literal=3 bindings=(subtypes of) (default from ExpressibleByStringLiteral) String)
+
+// CHECK: (solving component #
+// CHECK: literal=3 bindings=(subtypes of) (default from ExpressibleByIntegerLiteral) Int)
+
+// CHECK: (solving component #
+// CHECK: literal=3 bindings=(subtypes of) (default from ExpressibleByStringLiteral) String)
+
+// CHECK: (solving component #
+// CHECK: literal=3 bindings=(subtypes of) (default from ExpressibleByIntegerLiteral) Int)
+
+// CHECK: (solving component #
+// CHECK: literal=3 bindings=(subtypes of) (default from ExpressibleByStringLiteral) String)
+
+_ = "\(1), \(2), \(3), \(4)"
diff --git a/test/Constraints/overload.swift b/test/Constraints/overload.swift
index 9cb3a20..264bac6 100644
--- a/test/Constraints/overload.swift
+++ b/test/Constraints/overload.swift
@@ -186,3 +186,12 @@
overloadedMethod()
// expected-error@-1 {{missing argument for parameter 'n' in call}}
+
+// Ensure we select the overload of '??' returning T? rather than T.
+func SR3817(_ d: [String : Any], _ s: String, _ t: String) -> Any {
+ if let r = d[s] ?? d[t] {
+ return r
+ } else {
+ return 0
+ }
+}
diff --git a/test/Constraints/tuple_arguments.swift b/test/Constraints/tuple_arguments.swift
index 3bc62bf..57fe62d 100644
--- a/test/Constraints/tuple_arguments.swift
+++ b/test/Constraints/tuple_arguments.swift
@@ -1420,3 +1420,11 @@
block(c, c)
}
}
+
+// expected-error@+1 {{cannot create a single-element tuple with an element label}}
+func singleElementTupleArgument(completion: ((didAdjust: Bool)) -> Void) {
+ // TODO: Error could be improved.
+ // expected-error@+1 {{cannot convert value of type '(didAdjust: Bool)' to expected argument type 'Bool'}}
+ completion((didAdjust: true))
+}
+
diff --git a/test/Driver/bridging-pch.swift b/test/Driver/bridging-pch.swift
index 491a7ce..f2f7ea9 100644
--- a/test/Driver/bridging-pch.swift
+++ b/test/Driver/bridging-pch.swift
@@ -1,17 +1,17 @@
-// RUN: %swiftc_driver -typecheck -enable-bridging-pch -driver-print-actions -import-objc-header %S/Inputs/bridging-header.h %s 2>&1 | %FileCheck %s -check-prefix=YESPCHACT
+// RUN: %swiftc_driver -typecheck -driver-print-actions -import-objc-header %S/Inputs/bridging-header.h %s 2>&1 | %FileCheck %s -check-prefix=YESPCHACT
// YESPCHACT: 0: input, "{{.*}}Inputs/bridging-header.h", objc-header
// YESPCHACT: 1: generate-pch, {0}, pch
// YESPCHACT: 2: input, "{{.*}}bridging-pch.swift", swift
// YESPCHACT: 3: compile, {2, 1}, none
-// RUN: %swiftc_driver -typecheck -driver-print-actions -import-objc-header %S/Inputs/bridging-header.h %s 2>&1 | %FileCheck %s -check-prefix=NOPCHACT
+// RUN: %swiftc_driver -typecheck -disable-bridging-pch -driver-print-actions -import-objc-header %S/Inputs/bridging-header.h %s 2>&1 | %FileCheck %s -check-prefix=NOPCHACT
// NOPCHACT: 0: input, "{{.*}}bridging-pch.swift", swift
// NOPCHACT: 1: compile, {0}, none
-// RUN: %swiftc_driver -typecheck -enable-bridging-pch -driver-print-jobs -import-objc-header %S/Inputs/bridging-header.h %s 2>&1 | %FileCheck %s -check-prefix=YESPCHJOB
+// RUN: %swiftc_driver -typecheck -driver-print-jobs -import-objc-header %S/Inputs/bridging-header.h %s 2>&1 | %FileCheck %s -check-prefix=YESPCHJOB
// YESPCHJOB: {{.*}}swift -frontend {{.*}} -emit-pch -o {{.*}}bridging-header-{{.*}}.pch
// YESPCHJOB: {{.*}}swift -frontend {{.*}} -import-objc-header {{.*}}bridging-header-{{.*}}.pch
-// RUN: %swiftc_driver -typecheck -driver-print-jobs -import-objc-header %S/Inputs/bridging-header.h %s 2>&1 | %FileCheck %s -check-prefix=NOPCHJOB
+// RUN: %swiftc_driver -typecheck -disable-bridging-pch -driver-print-jobs -import-objc-header %S/Inputs/bridging-header.h %s 2>&1 | %FileCheck %s -check-prefix=NOPCHJOB
// NOPCHJOB: {{.*}}swift -frontend {{.*}} -import-objc-header {{.*}}Inputs/bridging-header.h
diff --git a/test/Inputs/clang-importer-sdk/swift-modules/Foundation.swift b/test/Inputs/clang-importer-sdk/swift-modules/Foundation.swift
index d30d1e2..219dc82 100644
--- a/test/Inputs/clang-importer-sdk/swift-modules/Foundation.swift
+++ b/test/Inputs/clang-importer-sdk/swift-modules/Foundation.swift
@@ -355,6 +355,8 @@
@objc(_swift_objectForKeyedSubscript:)
get { fatalError() }
}
+
+ public func nonObjCExtensionMethod<T>(_: T) {}
}
extension NSMutableDictionary {
public override subscript(_: Any) -> Any? {
diff --git a/test/Interpreter/classes.swift b/test/Interpreter/classes.swift
index 81c8636..c94522f 100644
--- a/test/Interpreter/classes.swift
+++ b/test/Interpreter/classes.swift
@@ -207,3 +207,29 @@
}
makeOne(Child.self).doSomething() // CHECK: Heaven!
+
+// https://bugs.swift.org/browse/SR-3840
+
+class BaseProperty {
+ var value: Int {
+ get { fatalError() }
+ set { fatalError() }
+ }
+
+ func increment() -> Self {
+ value += 1
+ return self
+ }
+}
+
+class DerivedProperty : BaseProperty {
+ override var value: Int {
+ get { return _value }
+ set { _value = newValue }
+ }
+
+ var _value: Int = 0
+}
+
+// CHECK: 1
+print(DerivedProperty().increment().value)
diff --git a/test/Misc/expression_too_complex.swift b/test/Misc/expression_too_complex.swift
index 116d75f..c1a8b62 100644
--- a/test/Misc/expression_too_complex.swift
+++ b/test/Misc/expression_too_complex.swift
@@ -1,4 +1,4 @@
-// RUN: %target-typecheck-verify-swift -solver-memory-threshold 4000
+// RUN: %target-typecheck-verify-swift -solver-memory-threshold 8000
var x = [1, 2, 3, 4.5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 ,19] // expected-error{{expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions}}
diff --git a/test/Misc/expression_too_complex_2.swift b/test/Misc/expression_too_complex_2.swift
new file mode 100644
index 0000000..06b40d9
--- /dev/null
+++ b/test/Misc/expression_too_complex_2.swift
@@ -0,0 +1,28 @@
+// RUN: %target-typecheck-verify-swift -solver-memory-threshold 32000
+// REQUIRES: OS=ios
+import UIKit
+class MyViewCell: UITableViewCell {
+ let View1 : UIView = UIView(frame: .zero)
+ let label1 = UILabel(frame: .zero)
+ let label2 = UILabel(frame: .zero)
+ let label3 = UILabel(frame: .zero)
+ required init?(coder aDecoder: NSCoder) { fatalError("no") }
+ override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
+ super.init(style: .default, reuseIdentifier: reuseIdentifier)
+ NSLayoutConstraint.activate([ // expected-error{{expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions}}
+ NSLayoutConstraint(item: View1, attribute: .top, relatedBy: .equal, toItem: label1, attribute: .top, multiplier: 1, constant: 1),
+ NSLayoutConstraint(item: View1, attribute: .top, relatedBy: .equal, toItem: label2, attribute: .top, multiplier: 1, constant: 1),
+ NSLayoutConstraint(item: View1, attribute: .top, relatedBy: .equal, toItem: label3, attribute: .top, multiplier: 1, constant: 1),
+ NSLayoutConstraint(item: View1, attribute: .top, relatedBy: .equal, toItem: label1, attribute: .top, multiplier: 1, constant: 1),
+ NSLayoutConstraint(item: label1, attribute: .top, relatedBy: .equal, toItem: label2, attribute: .top, multiplier: 1, constant: 1),
+ NSLayoutConstraint(item: label1, attribute: .top, relatedBy: .equal, toItem: label3, attribute: .top, multiplier: 1, constant: 1),
+ NSLayoutConstraint(item: label1, attribute: .top, relatedBy: .equal, toItem: label1, attribute: .top, multiplier: 1, constant: 1),
+ NSLayoutConstraint(item: label1, attribute: .top, relatedBy: .equal, toItem: label2, attribute: .top, multiplier: 1, constant: 1),
+ NSLayoutConstraint(item: label2, attribute: .top, relatedBy: .equal, toItem: label3, attribute: .top, multiplier: 1, constant: 1),
+ NSLayoutConstraint(item: label2, attribute: .top, relatedBy: .equal, toItem: label1, attribute: .top, multiplier: 1, constant: 1),
+ NSLayoutConstraint(item: label3, attribute: .top, relatedBy: .equal, toItem: label2, attribute: .top, multiplier: 1, constant: 1),
+ NSLayoutConstraint(item: label3, attribute: .top, relatedBy: .equal, toItem: label3, attribute: .top, multiplier: 1, constant: 1),
+ NSLayoutConstraint(item: label3, attribute: .top, relatedBy: .equal, toItem: label2, attribute: .top, multiplier: 1, constant: 1)
+ ])
+ }
+}
diff --git a/test/SILGen/Inputs/weak_other.swift b/test/SILGen/Inputs/weak_other.swift
new file mode 100644
index 0000000..cc4132a
--- /dev/null
+++ b/test/SILGen/Inputs/weak_other.swift
@@ -0,0 +1,23 @@
+public struct Flags {
+ public func asBoolean() -> Bool { return true }
+}
+
+public protocol Router : class {
+
+}
+
+extension Router {
+ public var flags: Flags { return Flags() }
+}
+
+public protocol Environment : class {
+ unowned var router: Router { get }
+}
+
+open class UI {
+ open unowned let environment: Environment
+
+ init(e: Environment) {
+ environment = e
+ }
+}
diff --git a/test/SILGen/capture-canonicalization.swift b/test/SILGen/capture-canonicalization.swift
new file mode 100644
index 0000000..6ecdf3d
--- /dev/null
+++ b/test/SILGen/capture-canonicalization.swift
@@ -0,0 +1,14 @@
+// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
+
+struct Foo<T> {}
+struct Bar {}
+
+extension Foo where T == Bar {
+ func foo(x: T) -> Bar {
+ // CHECK-LABEL: sil shared @{{.*}}3foo{{.*}}4foo2{{.*}} : $@convention(thin) (Bar) -> Bar
+ func foo2() -> Bar {
+ return x
+ }
+ return foo2()
+ }
+}
diff --git a/test/SILGen/default_arguments_generic.swift b/test/SILGen/default_arguments_generic.swift
index c88b06a..5a7e6f4 100644
--- a/test/SILGen/default_arguments_generic.swift
+++ b/test/SILGen/default_arguments_generic.swift
@@ -28,3 +28,21 @@
// CHECK: apply [[ZANG_DFLT_1]]<Int, Double>
Zim<Int>.zang(Double.self, 22)
}
+
+protocol Initializable {
+ init()
+}
+struct Generic<T: Initializable> {
+ init(_ value: T = T()) {}
+}
+struct InitializableImpl: Initializable {
+ init() {}
+}
+// CHECK-LABEL: sil hidden @_TF25default_arguments_generic17testInitializableFT_T_
+func testInitializable() {
+ // The ".init" is required to trigger the crash that used to happen.
+ _ = Generic<InitializableImpl>.init()
+ // CHECK: [[INIT:%.+]] = function_ref @_TFV25default_arguments_generic7GenericCfxGS0_x_
+ // CHECK: function_ref @_TIFV25default_arguments_generic7GenericcFxGS0_x_A_ : $@convention(thin) <τ_0_0 where τ_0_0 : Initializable> () -> @out τ_0_0
+ // CHECK: apply [[INIT]]<InitializableImpl>({{%.+}}, {{%.+}}) : $@convention(method) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @thin Generic<τ_0_0>.Type) -> Generic<τ_0_0>
+} // CHECK: end sil function '_TF25default_arguments_generic17testInitializableFT_T_'
diff --git a/test/SILGen/implicitly_unwrapped_optional.swift b/test/SILGen/implicitly_unwrapped_optional.swift
index 34a6f1c..e2dc62c 100644
--- a/test/SILGen/implicitly_unwrapped_optional.swift
+++ b/test/SILGen/implicitly_unwrapped_optional.swift
@@ -59,3 +59,14 @@
func bind_any() {
let object : AnyObject? = return_any()
}
+
+// CHECK-LABEL: sil hidden @_TF29implicitly_unwrapped_optional6sr3758FT_T_
+func sr3758() {
+ // Verify that there are no additional reabstractions introduced.
+ // CHECK: [[CLOSURE:%.+]] = function_ref @_TFF29implicitly_unwrapped_optional6sr3758FT_T_U_FGSQP__T_ : $@convention(thin) (@in Optional<Any>) -> ()
+ // CHECK: [[F:%.+]] = thin_to_thick_function [[CLOSURE]] : $@convention(thin) (@in Optional<Any>) -> () to $@callee_owned (@in Optional<Any>) -> ()
+ // CHECK: [[CALLEE:%.+]] = copy_value [[F]] : $@callee_owned (@in Optional<Any>) -> ()
+ // CHECK: = apply [[CALLEE]]({{%.+}}) : $@callee_owned (@in Optional<Any>) -> ()
+ let f: ((Any?) -> Void) = { (arg: Any!) in }
+ f(nil)
+} // CHECK: end sil function '_TF29implicitly_unwrapped_optional6sr3758FT_T_'
diff --git a/test/SILGen/materializeForSet.swift b/test/SILGen/materializeForSet.swift
index 0fde20c..f1d8667 100644
--- a/test/SILGen/materializeForSet.swift
+++ b/test/SILGen/materializeForSet.swift
@@ -385,6 +385,21 @@
increment(&t.abv)
}
+// Test for materializeForSet vs overriden computed property of classes.
+class BaseForOverride {
+ var valueStored: Int
+ var valueComputed: Int { get { } set { } }
+
+ init(valueStored: Int) {
+ self.valueStored = valueStored
+ }
+}
+
+class DerivedForOverride : BaseForOverride {
+ override var valueStored: Int { get { } set { } }
+ override var valueComputed: Int { get { } set { } }
+}
+
// Test for materializeForSet vs static properties of classes.
class ReferenceBeer {
@@ -514,6 +529,15 @@
f.computed = f.computed
}
+// CHECK-LABEL: sil_vtable DerivedForOverride {
+// CHECK: #BaseForOverride.valueComputed!getter.1: _TFC17materializeForSet18DerivedForOverrideg13valueComputedSi
+// CHECK: #BaseForOverride.valueComputed!setter.1: _TFC17materializeForSet18DerivedForOverrides13valueComputedSi
+// CHECK: #BaseForOverride.valueComputed!materializeForSet.1: _TFC17materializeForSet18DerivedForOverridem13valueComputedSi
+// CHECK: #BaseForOverride.valueStored!getter.1: _TFC17materializeForSet18DerivedForOverrideg11valueStoredSi
+// CHECK: #BaseForOverride.valueStored!setter.1: _TFC17materializeForSet18DerivedForOverrides11valueStoredSi
+// CHECK: #BaseForOverride.valueStored!materializeForSet.1: _TFC17materializeForSet18DerivedForOverridem11valueStoredSi
+// CHECK: }
+
// CHECK-LABEL: sil_witness_table hidden Bill: Totalled module materializeForSet {
// CHECK: method #Totalled.total!getter.1: @_TTWV17materializeForSet4BillS_8TotalledS_FS1_g5totalSi
// CHECK: method #Totalled.total!setter.1: @_TTWV17materializeForSet4BillS_8TotalledS_FS1_s5totalSi
diff --git a/test/SILGen/super-to-nonobjc-extension.swift b/test/SILGen/super-to-nonobjc-extension.swift
new file mode 100644
index 0000000..4038082
--- /dev/null
+++ b/test/SILGen/super-to-nonobjc-extension.swift
@@ -0,0 +1,14 @@
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen %s | %FileCheck %s
+// REQUIRES: objc_interop
+
+// rdar://problem/30030229
+
+import Foundation
+
+class MyDictionary: NSDictionary {
+ // CHECK-LABEL: sil hidden @_TFC4main12MyDictionary31callSuperNonObjCExtensionMethodfSiT_
+ func callSuperNonObjCExtensionMethod(_ x: Int) {
+ // CHECK-NOT: super_method {{.*}} #NSDictionary.nonObjCExtensionMethod
+ super.nonObjCExtensionMethod(x)
+ }
+}
diff --git a/test/SILGen/weak_multiple_modules.swift b/test/SILGen/weak_multiple_modules.swift
new file mode 100644
index 0000000..b8ace77
--- /dev/null
+++ b/test/SILGen/weak_multiple_modules.swift
@@ -0,0 +1,21 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: %target-swift-frontend -emit-module -emit-module-path=%t/weak_other.swiftmodule -module-name=weak_other %S/Inputs/weak_other.swift
+// RUN: %target-swift-frontend -I %t -emit-silgen %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime
+
+import weak_other
+
+// CHECK-LABEL: sil hidden @_TF21weak_multiple_modules11doSomethingFT2uiC10weak_other2UI_Sb : $@convention(thin) (@owned UI) -> Bool
+func doSomething(ui: UI) -> Bool {
+ // CHECK: ref_element_addr
+ // CHECK-objc: load_unowned
+ // CHECK-native: load [take]
+ // CHECK-native: strong_retain_unowned
+ // CHECK: open_existential_ref
+ // CHECK: witness_method
+ // CHECK: apply
+ // CHECK: open_existential_ref
+ // CHECK: function_ref
+ // CHECK: apply
+ // CHECK: return
+ return ui.environment.router.flags.asBoolean()
+}
diff --git a/test/SILOptimizer/devirt_nested_class.swift b/test/SILOptimizer/devirt_nested_class.swift
new file mode 100644
index 0000000..8c06a82
--- /dev/null
+++ b/test/SILOptimizer/devirt_nested_class.swift
@@ -0,0 +1,30 @@
+// RUN: %target-swift-frontend -emit-sil -O %s | %FileCheck %s
+
+fileprivate class Outer<T> {
+ class Inner<U> : Base<T, U> {
+ @_semantics("optimize.sil.never")
+ override func method<V>(v: V) {}
+ }
+}
+
+fileprivate class Base<T, U> {
+ @_semantics("optimize.sil.never")
+ func method<V>(v: V) {}
+}
+
+fileprivate class Derived<T, U> : Outer<T>.Inner<U> {}
+
+@_transparent
+fileprivate func bar<T, U, V>(b: Base<T, U>, v: V) {
+ b.method(v: v)
+}
+
+fileprivate func foo<T, U, V>(d: Outer<T>.Inner<U>, v: V) {
+ bar(b: d, v: v)
+}
+
+foo(d: Outer<Int>.Inner<Int>(), v: 0)
+
+// CHECK-LABEL: sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32
+// CHECK: function_ref @_TFCC19devirt_nested_class{{.*}}5Outer5Inner6methodurfT1vqd0___T_ : $@convention(method) <τ_0_0><τ_1_0><τ_2_0> (@in τ_2_0, @guaranteed Outer<τ_0_0>.Inner<τ_1_0>) -> ()
+// CHECK: return
diff --git a/test/Serialization/Inputs/inherited-initializer-base.swift b/test/Serialization/Inputs/inherited-initializer-base.swift
new file mode 100644
index 0000000..e342cb0
--- /dev/null
+++ b/test/Serialization/Inputs/inherited-initializer-base.swift
@@ -0,0 +1,10 @@
+open class Base {
+ public init(_ value: Int = 0) {}
+}
+
+public protocol Initializable {
+ init()
+}
+open class GenericBase<T: Initializable> {
+ public init(_ value: T = T()) {}
+}
diff --git a/test/Serialization/Inputs/multi-file-2.swift b/test/Serialization/Inputs/multi-file-2.swift
index 6bcafec..807d2b0 100644
--- a/test/Serialization/Inputs/multi-file-2.swift
+++ b/test/Serialization/Inputs/multi-file-2.swift
@@ -1,5 +1,5 @@
-// Do not put any classes in this file. It's part of the test that no classes
-// get serialized here.
+// Do not put any protocols in this file. It's part of the test that no
+// protocols get serialized here.
enum TheEnum {
case A, B, C(MyClass)
@@ -28,3 +28,8 @@
useEquatable(LocalEnum.A)
useEquatable(Wrapper.LocalEnum.A)
}
+
+class Base {
+ class var conflict: Int { return 0 }
+ var conflict: Int { return 1 }
+}
diff --git a/test/Serialization/inherited-initializer.swift b/test/Serialization/inherited-initializer.swift
new file mode 100644
index 0000000..30e15cf
--- /dev/null
+++ b/test/Serialization/inherited-initializer.swift
@@ -0,0 +1,54 @@
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: %target-swift-frontend -emit-module -o %t -module-name InheritedInitializerBase %S/Inputs/inherited-initializer-base.swift
+// RUN: %target-swift-frontend -emit-silgen -I %t %s | %FileCheck %s
+
+import InheritedInitializerBase
+
+class InheritsInit : Base {}
+
+// CHECK-LABEL: sil hidden @_TF4main10testSimpleFT_T_
+func testSimple() {
+ // CHECK: [[INIT:%.+]] = function_ref @_TFC4main12InheritsInitCfSiS0_
+ // CHECK: [[DEFAULT:%.+]] = function_ref @_TIFC24InheritedInitializerBase4BasecFSiS0_A_
+ // CHECK: [[ARG:%.+]] = apply [[DEFAULT]]()
+ // CHECK: apply [[INIT]]([[ARG]], {{%.+}})
+ _ = InheritsInit()
+
+ // CHECK: [[INIT:%.+]] = function_ref @_TFC4main12InheritsInitCfSiS0_
+ // CHECK: [[VALUE:%.+]] = integer_literal $Builtin.Int2048, 5
+ // CHECK: [[ARG:%.+]] = apply {{%.+}}([[VALUE]], {{%.+}}) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
+ // CHECK: apply [[INIT]]([[ARG]], {{%.+}})
+ _ = InheritsInit(5)
+} // CHECK: end sil function '_TF4main10testSimpleFT_T_'
+
+struct Reinitializable<T>: Initializable {
+ init() {}
+}
+
+class GenericSub<T: Initializable> : GenericBase<T> {}
+class ModifiedGenericSub<U> : GenericBase<Reinitializable<U>> {}
+class NonGenericSub : GenericBase<Reinitializable<Int>> {}
+
+// CHECK-LABEL: sil hidden @_TF4main11testGenericFT_T_
+func testGeneric() {
+ // CHECK: [[INIT:%.+]] = function_ref @_TFC4main10GenericSubCfxGS0_x_
+ // CHECK: [[TYPE:%.+]] = metatype $@thick GenericSub<Reinitializable<Int8>>.Type
+ // CHECK: [[DEFAULT:%.+]] = function_ref @_TIFC24InheritedInitializerBase11GenericBasecFxGS0_x_A_
+ // CHECK: apply [[DEFAULT]]<Reinitializable<Int8>>({{%.+}})
+ // CHECK: apply [[INIT]]<Reinitializable<Int8>>({{%.+}}, [[TYPE]])
+ _ = GenericSub<Reinitializable<Int8>>.init() // works around SR-3806
+
+ // CHECK: [[INIT:%.+]] = function_ref @_TFC4main18ModifiedGenericSubCfGVS_15Reinitializablex_GS0_x_
+ // CHECK: [[TYPE:%.+]] = metatype $@thick ModifiedGenericSub<Int16>.Type
+ // CHECK: [[DEFAULT:%.+]] = function_ref @_TIFC24InheritedInitializerBase11GenericBasecFxGS0_x_A_
+ // CHECK: apply [[DEFAULT]]<Reinitializable<Int16>>({{%.+}})
+ // CHECK: apply [[INIT]]<Int16>({{%.+}}, [[TYPE]])
+ _ = ModifiedGenericSub<Int16>()
+
+ // CHECK: [[INIT:%.+]] = function_ref @_TFC4main13NonGenericSubCfGVS_15ReinitializableSi_S0_
+ // CHECK: [[TYPE:%.+]] = metatype $@thick NonGenericSub.Type
+ // CHECK: [[DEFAULT:%.+]] = function_ref @_TIFC24InheritedInitializerBase11GenericBasecFxGS0_x_A_
+ // CHECK: apply [[DEFAULT]]<Reinitializable<Int>>({{%.+}})
+ // CHECK: apply [[INIT]]({{%.+}}, [[TYPE]])
+ _ = NonGenericSub()
+} // CHECK: end sil function '_TF4main11testGenericFT_T_'
\ No newline at end of file
diff --git a/test/Serialization/multi-file-nested-type-circularity.swift b/test/Serialization/multi-file-nested-type-circularity.swift
index 009a43d..dcf93c0 100644
--- a/test/Serialization/multi-file-nested-type-circularity.swift
+++ b/test/Serialization/multi-file-nested-type-circularity.swift
@@ -5,6 +5,8 @@
// RUN: %target-swift-frontend -emit-module -module-name Multi %t/multi-file.swiftmodule %t/multi-file-2.swiftmodule -o %t -print-stats 2>&1 | %FileCheck %s
// RUN: %target-swift-frontend -emit-module -module-name Multi %t/multi-file-2.swiftmodule %t/multi-file.swiftmodule -o %t -print-stats 2>&1 | %FileCheck %s
+// REQUIRES: asserts
+
// CHECK: Statistics
// CHECK: 1 Serialization - # of same-module nested types resolved without lookup
diff --git a/test/Serialization/multi-file-nested-type-extension.swift b/test/Serialization/multi-file-nested-type-extension.swift
index 8acc8b0..7e27c97 100644
--- a/test/Serialization/multi-file-nested-type-extension.swift
+++ b/test/Serialization/multi-file-nested-type-extension.swift
@@ -7,6 +7,8 @@
// RUN: %target-swift-frontend -emit-module -module-name Multi %t/multi-file-2.swiftmodule %t/multi-file.swiftmodule %t/multi-file-3.swiftmodule -o %t -print-stats 2>&1 | %FileCheck %s
// RUN: %target-swift-frontend -emit-module -module-name Multi %t/multi-file-2.swiftmodule %t/multi-file-3.swiftmodule %t/multi-file.swiftmodule -o %t -print-stats 2>&1 | %FileCheck %s
+// REQUIRES: asserts
+
// CHECK: Statistics
// CHECK: 1 Serialization - # of same-module nested types resolved without lookup
diff --git a/test/Serialization/multi-file-nested-type-simple.swift b/test/Serialization/multi-file-nested-type-simple.swift
index 4a683c3..6220511 100644
--- a/test/Serialization/multi-file-nested-type-simple.swift
+++ b/test/Serialization/multi-file-nested-type-simple.swift
@@ -13,6 +13,8 @@
// RUN: %target-swift-frontend -emit-module -module-name Multi %t/multi-file.swiftmodule %t/multi-file-2.swiftmodule -o %t -print-stats 2>&1 | %FileCheck -check-prefix=DISABLED %s
// RUN: %target-swift-frontend -emit-module -module-name Multi %t/multi-file-2.swiftmodule %t/multi-file.swiftmodule -o %t -print-stats 2>&1 | %FileCheck -check-prefix=DISABLED %s
+// REQUIRES: asserts
+
// CHECK: 4 Serialization - # of same-module nested types resolved without lookup
// DISABLED: Statistics
// DISABLED-NOT: same-module nested types resolved without lookup
diff --git a/test/Serialization/multi-file.swift b/test/Serialization/multi-file.swift
index b8b5d78..3b87bc6 100644
--- a/test/Serialization/multi-file.swift
+++ b/test/Serialization/multi-file.swift
@@ -24,8 +24,8 @@
foo(EquatableEnum.A)
}
-// THIS-FILE-DAG: CLASS_DECL
-// OTHER-FILE-NEG-NOT: CLASS_DECL
+// THIS-FILE-DAG: PROTOCOL_DECL
+// OTHER-FILE-NEG-NOT: PROTOCOL_DECL
// OTHER-FILE-DAG: ENUM_DECL
// THIS-FILE-NEG-NOT: ENUM_DECL
@@ -54,3 +54,8 @@
private struct Generic<T> {
// THIS-FILE-DAG: GENERIC_TYPE_PARAM_DECL
}
+
+class Sub: Base {
+ override class var conflict: Int { return 100 }
+ override var conflict: Int { return 200 }
+}
diff --git a/test/SourceKit/Misc/ignore_bridging_pch.swift b/test/SourceKit/Misc/ignore_bridging_pch.swift
new file mode 100644
index 0000000..b2c9812
--- /dev/null
+++ b/test/SourceKit/Misc/ignore_bridging_pch.swift
@@ -0,0 +1,7 @@
+// RUN: %sourcekitd-test -req=complete -pos=5:3 %s -- -enable-bridging-pch %s | %FileCheck %s
+// RUN: %sourcekitd-test -req=complete -pos=5:3 %s -- -disable-bridging-pch %s | %FileCheck %s
+
+var s = 10
+s.
+
+// CHECK: littleEndian
diff --git a/test/api-digester/source-stability.swift.expected b/test/api-digester/source-stability.swift.expected
index afef4ce..86e7300 100644
--- a/test/api-digester/source-stability.swift.expected
+++ b/test/api-digester/source-stability.swift.expected
@@ -12,6 +12,7 @@
Protocol MutableIndexable has been removed (deprecated)
Protocol RandomAccessIndexable has been removed (deprecated)
Protocol RangeReplaceableIndexable has been removed (deprecated)
+Constructor String.init(stringInterpolationSegment:) has been removed
Func Array.append(contentsOf:) has been removed
Func ArraySlice.append(contentsOf:) has been removed
Func ContiguousArray.append(contentsOf:) has been removed
@@ -34,6 +35,7 @@
Constructor RangeReplaceableRandomAccessSlice.init(base:bounds:) has 2nd parameter type change from Range<Base.Index> to Range<RangeReplaceableRandomAccessSlice.Index>
Constructor RangeReplaceableSlice.init(base:bounds:) has 2nd parameter type change from Range<Base.Index> to Range<RangeReplaceableSlice.Index>
Constructor Slice.init(base:bounds:) has 2nd parameter type change from Range<Base.Index> to Range<Slice.Index>
+Constructor String.init(stringInterpolationSegment:) has 1st parameter type change from String to T
Func AnyBidirectionalCollection.makeIterator() has return type change from AnyIterator<Element> to AnyBidirectionalCollection.Iterator
Func AnyCollection.makeIterator() has return type change from AnyIterator<Element> to AnyCollection.Iterator
Func AnyRandomAccessCollection.makeIterator() has return type change from AnyIterator<Element> to AnyRandomAccessCollection.Iterator
diff --git a/test/decl/ext/extensions.swift b/test/decl/ext/extensions.swift
index f448331..6c78ec8 100644
--- a/test/decl/ext/extensions.swift
+++ b/test/decl/ext/extensions.swift
@@ -113,3 +113,15 @@
extension X3 {
func foo() -> Int { return 0 }
}
+
+// Make sure the test case from https://bugs.swift.org/browse/SR-3847 doesn't
+// cause problems when the later extension is incorrectly nested inside another
+// declaration.
+extension C1.NestedStruct {
+ static let originalValue = 0
+}
+struct WrapperContext {
+ extension C1.NestedStruct { // expected-error {{declaration is only valid at file scope}}
+ static let propUsingMember = originalValue // expected-error {{use of unresolved identifier 'originalValue'}}
+ }
+}
diff --git a/test/decl/nested/type_in_type.swift b/test/decl/nested/type_in_type.swift
index 1470413..b247d01 100644
--- a/test/decl/nested/type_in_type.swift
+++ b/test/decl/nested/type_in_type.swift
@@ -337,3 +337,17 @@
return f2()
}
}
+
+// https://bugs.swift.org/browse/SR-3847: Resolve members in inner types.
+// This first extension isn't necessary; we could have put 'originalValue' in
+// the original declaration.
+extension OuterNonGenericClass.InnerNonGenericBase {
+ static let originalValue = 0
+}
+// Each of these two cases used to crash.
+extension OuterNonGenericClass.InnerNonGenericBase {
+ static let propUsingMember = originalValue
+}
+extension OuterNonGenericClass.InnerNonGenericClass1 {
+ static let anotherPropUsingMember = originalValue
+}
diff --git a/test/stdlib/Dispatch.swift b/test/stdlib/Dispatch.swift
index 681ee85..419e0b9 100644
--- a/test/stdlib/Dispatch.swift
+++ b/test/stdlib/Dispatch.swift
@@ -101,3 +101,31 @@
})
}
}
+
+DispatchAPI.test("DispatchTime.addSubtract") {
+ var then = DispatchTime.now() + Double.infinity
+ expectEqual(DispatchTime.distantFuture, then)
+
+ then = DispatchTime.now() + Double.nan
+ expectEqual(DispatchTime.distantFuture, then)
+
+ then = DispatchTime.now() - Double.infinity
+ expectEqual(DispatchTime(uptimeNanoseconds: 1), then)
+
+ then = DispatchTime.now() - Double.nan
+ expectEqual(DispatchTime(uptimeNanoseconds: 1), then)
+}
+
+DispatchAPI.test("DispatchWallTime.addSubtract") {
+ var then = DispatchWallTime.now() + Double.infinity
+ expectEqual(DispatchWallTime.distantFuture, then)
+
+ then = DispatchWallTime.now() + Double.nan
+ expectEqual(DispatchWallTime.distantFuture, then)
+
+ then = DispatchWallTime.now() - Double.infinity
+ expectEqual(DispatchWallTime.distantFuture.rawValue - UInt64(1), then.rawValue)
+
+ then = DispatchWallTime.now() - Double.nan
+ expectEqual(DispatchWallTime.distantFuture.rawValue - UInt64(1), then.rawValue)
+}
diff --git a/test/stdlib/collection-combinatorics.swift.gyb b/test/stdlib/collection-combinatorics.swift.gyb
new file mode 100644
index 0000000..f4c008c
--- /dev/null
+++ b/test/stdlib/collection-combinatorics.swift.gyb
@@ -0,0 +1,51 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: %gyb %s > %t/collection-combinatorics.swift
+// RUN: %target-swift-frontend -typecheck -verify %t/collection-combinatorics.swift
+
+// It should be possible to conform to any combination of
+// (1 + RangeReplaceable) * (1 + Bidirectional + RandomAccess) * (1 + Mutable)
+// Collection and get reasonable default implementations for slicing
+// operations from
+// the standard library.
+
+% for mutable in ['', 'Mutable']:
+% for rangeReplaceable in ['', 'RangeReplaceable']:
+% for capability in ['', 'Bidirectional', 'RandomAccess']:
+
+struct ${mutable}${rangeReplaceable}${capability}Butt
+ : ${mutable}Collection
+% if rangeReplaceable:
+ , ${rangeReplaceable}Collection
+% end
+% if capability:
+ , ${capability}Collection
+% end
+{
+ subscript(i: Int) -> Int {
+ get { return 0 }
+% if mutable:
+ set { }
+% end
+ }
+
+% if capability:
+ func index(before i: Int) -> Int {
+ return i - 1
+ }
+% end
+ func index(after i: Int) -> Int {
+ return i + 1
+ }
+
+ var startIndex: Int { return .min }
+ var endIndex: Int { return .max }
+
+% if rangeReplaceable:
+ init() {}
+
+ mutating func replaceSubrange<C: Collection>(_: Range<Int>, with: C)
+ where C.Iterator.Element == Int
+ {}
+% end
+}
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
index 787030e..2ff19fa 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
@@ -370,6 +370,9 @@
continue;
if (Arg == "-embed-bitcode")
continue;
+ if (Arg == "-enable-bridging-pch" ||
+ Arg == "-disable-bridging-pch")
+ continue;
NewArgs.push_back(CArg);
}
}
diff --git a/validation-test/Sema/interpolation_placeholders.swift b/validation-test/Sema/interpolation_placeholders.swift
new file mode 100644
index 0000000..519d3cb
--- /dev/null
+++ b/validation-test/Sema/interpolation_placeholders.swift
@@ -0,0 +1,4 @@
+// RUN: not %target-swift-frontend -typecheck %s
+
+let query = "<#...#>=\(<#...#>)&<#...#>=\(<#...#>)&<#...#>=\(<#...#>)&<#...#>=\(<#...#>)&<#...#>=\(<#...#>)&<#...#>=\(<#...#>)&<#...#>=\(<#...#>)&<#...#>=\(<#...#>)&<#...#>=\(<#...#>)&<#...#>=\(<#...#>)&<#...#>=\(<#...#>)&<#...#>=\(<#...#>)&<#...#>=\(<#...#>)&<#...#>=\(<#...#>)&<#...#>=\(<#...#>)&<#...#>=\(<#...#>)"
+
diff --git a/validation-test/Sema/protocol_typo_correction.swift b/validation-test/Sema/protocol_typo_correction.swift
new file mode 100644
index 0000000..14feac4
--- /dev/null
+++ b/validation-test/Sema/protocol_typo_correction.swift
@@ -0,0 +1,27 @@
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: %target-swift-frontend -emit-module -D LIB %s -o %t/Lib.swiftmodule
+// RUN: %target-swift-frontend -I %t -typecheck %s -verify
+// REQUIRES: objc_interop
+
+#if LIB
+
+import Foundation
+
+@objc public protocol Proto {
+ @objc optional func method(_: Int, for object: NSObject, dividing double: Double)
+}
+
+#else
+
+import Foundation
+import Lib
+
+class Impl: Proto {
+ func methodWithInt(_: Int, forObject object: NSObject, dividingDouble: Double) { }
+ // expected-warning@-1 {{instance method 'methodWithInt(_:forObject:dividingDouble:)' nearly matches optional requirement 'method(_:for:dividing:)' of protocol 'Proto'}}
+ // expected-note@-2{{rename to 'method(_:for:dividing:)' to satisfy this requirement}}{{8-21=method}}{{30-39=for}}{{58-58=dividing }}{{none}}
+ // expected-note@-3{{move 'methodWithInt(_:forObject:dividingDouble:)' to an extension to silence this warning}}
+ // expected-note@-4{{make 'methodWithInt(_:forObject:dividingDouble:)' private to silence this warning}}{{3-3=private }}
+}
+
+#endif
diff --git a/validation-test/compiler_crashers_2_fixed/0068-sr3853.swift b/validation-test/compiler_crashers_2_fixed/0068-sr3853.swift
new file mode 100644
index 0000000..07b705f
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0068-sr3853.swift
@@ -0,0 +1,22 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: %target-swift-frontend -emit-module %s -DLIBRARY -I %S/Inputs/0068-sr3853/ -o %t/Lib.swiftmodule
+// RUN: %target-swift-frontend -emit-sil -primary-file %s %S/Inputs/0068-sr3853/other.swift -I %S/Inputs/0068-sr3853/ -I %t -module-name main -DVALID
+
+// Try again in an error configuration to make sure we don't crash.
+// RUN: %target-swift-frontend -emit-sil -primary-file %s %S/Inputs/0068-sr3853/other.swift -I %S/Inputs/0068-sr3853/ -I %t -module-name main
+
+// REQUIRES: objc_interop
+
+#if LIBRARY
+
+import BaseLib
+
+public class GrandSub: Sub {}
+
+#else
+
+import Lib
+
+func foo(object: GrandSub) { }
+
+#endif
\ No newline at end of file
diff --git a/validation-test/compiler_crashers_2_fixed/Inputs/0068-sr3853/BaseLib.h b/validation-test/compiler_crashers_2_fixed/Inputs/0068-sr3853/BaseLib.h
new file mode 100644
index 0000000..f8d6559
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/Inputs/0068-sr3853/BaseLib.h
@@ -0,0 +1,10 @@
+@import Foundation;
+
+@interface Base: NSObject
+- (instancetype)initWithCustomField:(NSInteger)value NS_DESIGNATED_INITIALIZER;
+- (instancetype)initConvenience;
+@end
+
+@interface Sub: Base
+- (instancetype)initWithCustomField:(NSInteger)value NS_DESIGNATED_INITIALIZER;
+@end
diff --git a/validation-test/compiler_crashers_2_fixed/Inputs/0068-sr3853/module.modulemap b/validation-test/compiler_crashers_2_fixed/Inputs/0068-sr3853/module.modulemap
new file mode 100644
index 0000000..452c58b
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/Inputs/0068-sr3853/module.modulemap
@@ -0,0 +1,4 @@
+module BaseLib {
+ header "BaseLib.h"
+ export *
+}
diff --git a/validation-test/compiler_crashers_2_fixed/Inputs/0068-sr3853/other.swift b/validation-test/compiler_crashers_2_fixed/Inputs/0068-sr3853/other.swift
new file mode 100644
index 0000000..50290c3
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/Inputs/0068-sr3853/other.swift
@@ -0,0 +1,13 @@
+import BaseLib
+
+extension Base {
+#if VALID
+ convenience init(foo: String) {
+ fatalError()
+ }
+#else
+ init(foo: String) {
+ fatalError()
+ }
+#endif
+}