diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index db3720db146c2..6b03828649b41 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -245,6 +245,9 @@ ERROR(no_candidates_match_result_type,none, "no '%0' candidates produce the expected contextual result type %1", (StringRef, Type)) +ERROR(cannot_infer_closure_parameter_type,none, + "unable to infer type of a closure parameter %0 in the current context", + (StringRef)) ERROR(cannot_infer_closure_type,none, "unable to infer closure type in the current context", ()) ERROR(cannot_infer_closure_result_type,none, diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 3e29c740aa6c1..892d1c1d41d84 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -3043,12 +3043,21 @@ ProtocolConformanceRef ReplaceOpaqueTypesWithUnderlyingTypes:: operator()(CanType maybeOpaqueType, Type replacementType, ProtocolDecl *protocol) const { auto abstractRef = ProtocolConformanceRef(protocol); - + auto archetypeAndRoot = getArchetypeAndRootOpaqueArchetype(maybeOpaqueType); if (!archetypeAndRoot) { - assert(maybeOpaqueType->isTypeParameter() || - maybeOpaqueType->is()); - return abstractRef; + if (maybeOpaqueType->isTypeParameter() || + maybeOpaqueType->is()) + return abstractRef; + + // SIL type lowering may have already substituted away the opaque type, in + // which case we'll end up "substituting" the same type. + if (maybeOpaqueType->isEqual(replacementType)) { + return inContext->getParentModule() + ->lookupConformance(replacementType, protocol); + } + + llvm_unreachable("origType should have been an opaque type or type parameter"); } auto archetype = archetypeAndRoot->first; @@ -3510,24 +3519,28 @@ static Type getMemberForBaseType(LookupConformanceFn lookupConformances, // Retrieve the type witness. auto witness = - conformance.getConcrete()->getTypeWitness(assocType, options); - if (!witness || witness->hasError()) + conformance.getConcrete()->getTypeWitnessAndDecl(assocType, options); + + auto witnessTy = witness.getWitnessType(); + if (!witnessTy || witnessTy->hasError()) return failed(); // This is a hacky feature allowing code completion to migrate to // using Type::subst() without changing output. if (options & SubstFlags::DesugarMemberTypes) { - if (auto *aliasType = - dyn_cast(witness.getPointer())) { - if (!aliasType->is()) - witness = aliasType->getSinglyDesugaredType(); - } + if (auto *aliasType = dyn_cast(witnessTy.getPointer())) + witnessTy = aliasType->getSinglyDesugaredType(); + + // Another hack. If the type witness is a opaque result type. They can + // only be referred using the name of the associated type. + if (witnessTy->is()) + witnessTy = witness.getWitnessDecl()->getDeclaredInterfaceType(); } - if (witness->is()) + if (witnessTy->is()) return failed(); - return witness; + return witnessTy; } return failed(); diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index 242627b7e7fa0..ff5034f10f527 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -379,12 +379,16 @@ static void collectPossibleCalleesByQualifiedLookup( tyExpr->getTypeLoc().setType(nullptr); } - auto baseTyOpt = getTypeOfCompletionContextExpr( - DC.getASTContext(), &DC, CompletionTypeCheckKind::Normal, baseExpr, ref); - if (!baseTyOpt) - return; - - auto baseTy = (*baseTyOpt)->getWithoutSpecifierType(); + Type baseTy = baseExpr->getType(); + if (!baseTy || baseTy->is()) { + auto baseTyOpt = getTypeOfCompletionContextExpr( + DC.getASTContext(), &DC, CompletionTypeCheckKind::Normal, baseExpr, + ref); + if (!baseTyOpt) + return; + baseTy = *baseTyOpt; + } + baseTy = baseTy->getWithoutSpecifierType(); if (!baseTy->getMetatypeInstanceType()->mayHaveMembers()) return; diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index 5004872a1192b..cc75929674201 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -955,13 +955,6 @@ void SILGenModule::emitConstructor(ConstructorDecl *decl) { if (isa(decl->getDeclContext())) return; - // Always-unavailable imported constructors are factory methods - // that have been imported as constructors and then hidden by an - // imported init method. - if (decl->hasClangNode() && - decl->getAttrs().isUnavailable(decl->getASTContext())) - return; - SILDeclRef constant(decl); DeclContext *declCtx = decl->getDeclContext(); diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp index dd6a0f8d842c9..596c6be33d2db 100644 --- a/lib/SILGen/SILGenConstructor.cpp +++ b/lib/SILGen/SILGenConstructor.cpp @@ -252,6 +252,8 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF, selfTy.getFieldType(field, SGF.SGM.M, SGF.getTypeExpansionContext()); RValue value; + FullExpr scope(SGF.Cleanups, field->getParentPatternBinding()); + // If it's memberwise initialized, do so now. if (field->isMemberwiseInitialized(/*preferDeclaredProperties=*/false)) { assert(elti != eltEnd && "number of args does not match number of fields"); @@ -276,7 +278,6 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF, } // Cleanup after this initialization. - FullExpr scope(SGF.Cleanups, field->getParentPatternBinding()); SILValue v = maybeEmitPropertyWrapperInitFromValue(SGF, Loc, field, subs, std::move(value)) .forwardAsSingleStorageValue(SGF, fieldTy, Loc); diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index 0782046b41413..2d76e6909691a 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -1090,27 +1090,25 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const { // resolved and had to be bound to a placeholder "hole" type. cs.increaseScore(SK_Hole); + ConstraintFix *fix = nullptr; if (auto *GP = TypeVar->getImpl().getGenericParameter()) { auto path = dstLocator->getPath(); // Drop `generic parameter` locator element so that all missing // generic parameters related to the same path can be coalesced later. - auto *fix = DefaultGenericArgument::create( + fix = DefaultGenericArgument::create( cs, GP, cs.getConstraintLocator(dstLocator->getAnchor(), path.drop_back())); - if (cs.recordFix(fix)) - return true; + } else if (TypeVar->getImpl().isClosureParameterType()) { + fix = SpecifyClosureParameterType::create(cs, dstLocator); } else if (TypeVar->getImpl().isClosureResultType()) { - auto *fix = SpecifyClosureReturnType::create( - cs, TypeVar->getImpl().getLocator()); - if (cs.recordFix(fix)) - return true; + fix = SpecifyClosureReturnType::create(cs, dstLocator); } else if (srcLocator->getAnchor() && isa(srcLocator->getAnchor())) { - auto *fix = SpecifyObjectLiteralTypeImport::create( - cs, TypeVar->getImpl().getLocator()); - if (cs.recordFix(fix)) - return true; + fix = SpecifyObjectLiteralTypeImport::create(cs, dstLocator); } + + if (fix && cs.recordFix(fix)) + return true; } } diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 89f77ec1f6257..687f70db90e47 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -41,6 +41,12 @@ using namespace swift; using namespace constraints; +static bool hasFixFor(const Solution &solution, ConstraintLocator *locator) { + return llvm::any_of(solution.Fixes, [&locator](const ConstraintFix *fix) { + return fix->getLocator() == locator; + }); +} + FailureDiagnostic::~FailureDiagnostic() {} bool FailureDiagnostic::diagnose(bool asNote) { @@ -6127,6 +6133,74 @@ bool MissingContextualBaseInMemberRefFailure::diagnoseAsError() { return true; } +bool UnableToInferClosureParameterType::diagnoseAsError() { + auto *closure = castToExpr(getRawAnchor()); + + // Let's check whether this closure is an argument to + // a call which couldn't be properly resolved e.g. + // missing member or invalid contextual reference and + // if so let's not diagnose this problem because main + // issue here is inability to establish context for + // closure inference. + // + // TODO(diagnostics): Once we gain an ability to determine + // originating source of type holes this check could be + // significantly simplified. + { + auto &solution = getSolution(); + + // If there is a contextual mismatch associated with this + // closure, let's not diagnose any parameter type issues. + if (hasFixFor(solution, getConstraintLocator( + closure, LocatorPathElt::ContextualType()))) + return false; + + if (auto *parentExpr = findParentExpr(closure)) { + while (parentExpr && + (isa(parentExpr) || isa(parentExpr))) { + parentExpr = findParentExpr(parentExpr); + } + + if (parentExpr) { + // Missing or invalid member reference in call. + if (auto *AE = dyn_cast(parentExpr)) { + if (getType(AE->getFn())->isHole()) + return false; + } + + // Any fix anchored on parent expression makes it unnecessary + // to diagnose unability to infer parameter type because it's + // an indication that proper context couldn't be established to + // resolve the closure. + if (llvm::any_of(solution.Fixes, + [&parentExpr](const ConstraintFix *fix) -> bool { + return fix->getAnchor() == parentExpr; + })) + return false; + } + } + } + + auto paramIdx = getLocator() + ->castLastElementTo() + .getIndex(); + + auto *PD = closure->getParameters()->get(paramIdx); + + llvm::SmallString<16> id; + llvm::raw_svector_ostream OS(id); + + if (PD->isAnonClosureParam()) { + OS << "$" << paramIdx; + } else { + OS << "'" << PD->getParameterName() << "'"; + } + + auto loc = PD->isAnonClosureParam() ? getLoc() : PD->getLoc(); + emitDiagnosticAt(loc, diag::cannot_infer_closure_parameter_type, OS.str()); + return true; +} + bool UnableToInferClosureReturnType::diagnoseAsError() { auto *closure = castToExpr(getRawAnchor()); diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 79a1586f5dc91..709bb55bfc6b1 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -1973,6 +1973,15 @@ class MissingContextualBaseInMemberRefFailure final : public FailureDiagnostic { bool diagnoseAsError(); }; +class UnableToInferClosureParameterType final : public FailureDiagnostic { +public: + UnableToInferClosureParameterType(const Solution &solution, + ConstraintLocator *locator) + : FailureDiagnostic(solution, locator) {} + + bool diagnoseAsError(); +}; + class UnableToInferClosureReturnType final : public FailureDiagnostic { public: UnableToInferClosureReturnType(const Solution &solution, diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index dfb2d5b98eab2..0206d04c3ed99 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -22,6 +22,7 @@ #include "ConstraintSystem.h" #include "OverloadChoice.h" #include "swift/AST/Expr.h" +#include "swift/AST/ParameterList.h" #include "swift/AST/Type.h" #include "swift/AST/Types.h" #include "swift/Basic/SourceManager.h" @@ -1226,6 +1227,38 @@ SpecifyBaseTypeForContextualMember *SpecifyBaseTypeForContextualMember::create( SpecifyBaseTypeForContextualMember(cs, member, locator); } +std::string SpecifyClosureParameterType::getName() const { + std::string name; + llvm::raw_string_ostream OS(name); + + auto *closure = cast(getAnchor()); + auto paramLoc = + getLocator()->castLastElementTo(); + + auto *PD = closure->getParameters()->get(paramLoc.getIndex()); + + OS << "specify type for parameter "; + if (PD->isAnonClosureParam()) { + OS << "$" << paramLoc.getIndex(); + } else { + OS << "'" << PD->getParameterName() << "'"; + } + + return OS.str(); +} + +bool SpecifyClosureParameterType::diagnose(const Solution &solution, + bool asNote) const { + UnableToInferClosureParameterType failure(solution, getLocator()); + return failure.diagnose(asNote); +} + +SpecifyClosureParameterType * +SpecifyClosureParameterType::create(ConstraintSystem &cs, + ConstraintLocator *locator) { + return new (cs.getAllocator()) SpecifyClosureParameterType(cs, locator); +} + bool SpecifyClosureReturnType::diagnose(const Solution &solution, bool asNote) const { UnableToInferClosureReturnType failure(solution, getLocator()); diff --git a/lib/Sema/CSFix.h b/lib/Sema/CSFix.h index f06255de30120..1bee47cc0054f 100644 --- a/lib/Sema/CSFix.h +++ b/lib/Sema/CSFix.h @@ -232,6 +232,10 @@ enum class FixKind : uint8_t { /// inferred and has to be specified explicitly. SpecifyBaseTypeForContextualMember, + /// Type of the closure parameter used in the body couldn't be inferred + /// and has to be specified explicitly. + SpecifyClosureParameterType, + /// Closure return type has to be explicitly specified because it can't be /// inferred in current context e.g. because it's a multi-statement closure. SpecifyClosureReturnType, @@ -251,7 +255,7 @@ enum class FixKind : uint8_t { /// A warning fix that allows a coercion to perform a force-cast. AllowCoercionToForceCast, - + /// Allow key path root type mismatch when applying a key path that has a /// root type not convertible to the type of the base instance. AllowKeyPathRootTypeMismatch, @@ -1706,6 +1710,19 @@ class SpecifyBaseTypeForContextualMember final : public ConstraintFix { create(ConstraintSystem &cs, DeclNameRef member, ConstraintLocator *locator); }; +class SpecifyClosureParameterType final : public ConstraintFix { + SpecifyClosureParameterType(ConstraintSystem &cs, ConstraintLocator *locator) + : ConstraintFix(cs, FixKind::SpecifyClosureParameterType, locator) {} + +public: + std::string getName() const; + + bool diagnose(const Solution &solution, bool asNote = false) const; + + static SpecifyClosureParameterType *create(ConstraintSystem &cs, + ConstraintLocator *locator); +}; + class SpecifyClosureReturnType final : public ConstraintFix { SpecifyClosureReturnType(ConstraintSystem &cs, ConstraintLocator *locator) : ConstraintFix(cs, FixKind::SpecifyClosureReturnType, locator) {} diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 0e34b060438e7..6aaf4301dd68f 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -914,6 +914,35 @@ namespace { }; } // end anonymous namespace +namespace { +// Check if \p E is a call expression to curried thunk of "KeyPath as function". +// i.e. '{ `$kp$` in { $0[keyPath: $kp$] } }(keypath)' +static bool isKeyPathCurriedThunkCallExpr(Expr *E) { + auto CE = dyn_cast(E); + if (!CE) + return false; + auto thunk = dyn_cast(CE->getFn()); + if (!thunk) + return false; + if (thunk->getParameters()->size() != 1 || + thunk->getParameters()->get(0)->getParameterName().str() != "$kp$") + return false; + + auto PE = dyn_cast(CE->getArg()); + if (!PE) + return false; + return isa(PE->getSubExpr()); +} + +// Extract the keypath expression from the curried thunk expression. +static Expr *extractKeyPathFromCurryThunkCall(Expr *E) { + assert(isKeyPathCurriedThunkCallExpr(E)); + auto call = cast(E); + auto arg = cast(call->getArg()); + return arg->getSubExpr(); +} +} // end anonymous namespace + namespace { class ConstraintGenerator : public ExprVisitor { @@ -2167,8 +2196,12 @@ namespace { auto declaredTy = param->getType(); externalType = CS.openUnboundGenericType(declaredTy, paramLoc); } else { + // Let's allow parameters which haven't been explicitly typed + // to become holes by default, this helps in situations like + // `foo { a in }` where `foo` doesn't exist. externalType = CS.createTypeVariable( - paramLoc, TVO_CanBindToInOut | TVO_CanBindToNoEscape); + paramLoc, + TVO_CanBindToInOut | TVO_CanBindToNoEscape | TVO_CanBindToHole); } closureParams.push_back(param->toFunctionParam(externalType)); @@ -3781,6 +3814,12 @@ namespace { continue; } + // Extract keypath from '{ `$kp$` in { $0[keyPath: $kp$] } }(keypath)' + if (isKeyPathCurriedThunkCallExpr(expr)) { + expr = extractKeyPathFromCurryThunkCall(expr); + continue; + } + // Restore '@autoclosure'd value. if (auto ACE = dyn_cast(expr)) { // This is only valid if the closure doesn't have parameters. @@ -3788,6 +3827,7 @@ namespace { expr = ACE->getSingleExpressionBody(); continue; } + llvm_unreachable("other AutoClosureExpr must be handled specially"); } // Remove any semantic expression injected by typechecking. diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 211890bfa72d3..e84fe67d7c071 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -5682,6 +5682,19 @@ static bool isForKeyPathSubscript(ConstraintSystem &cs, return false; } +static bool isForKeyPathSubscriptWithoutLabel(ConstraintSystem &cs, + ConstraintLocator *locator) { + if (!locator || !locator->getAnchor()) + return false; + + if (auto *SE = dyn_cast(locator->getAnchor())) { + auto *indexExpr = SE->getIndex(); + return isa(indexExpr) && + isa(indexExpr->getSemanticsProvidingExpr()); + } + return false; +} + /// Determine whether all of the given candidate overloads /// found through conditional conformances of a given base type. /// This is useful to figure out whether it makes sense to @@ -5809,7 +5822,13 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, MemberLookupResult result; result.OverallResult = MemberLookupResult::HasResults; - if (isForKeyPathSubscript(*this, memberLocator)) { + // Add key path result. + // If we are including inaccessible members, check for the use of a keypath + // subscript without a `keyPath:` label. Add it to the result so that it + // can be caught by the missing argument label checking later. + if (isForKeyPathSubscript(*this, memberLocator) || + (isForKeyPathSubscriptWithoutLabel(*this, memberLocator) + && includeInaccessibleMembers)) { if (baseTy->isAnyObject()) { result.addUnviable( OverloadChoice(baseTy, OverloadChoiceKind::KeyPathApplication), @@ -9584,6 +9603,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( case FixKind::AllowTupleSplatForSingleParameter: case FixKind::AllowInvalidUseOfTrailingClosure: case FixKind::AllowNonClassTypeToConvertToAnyObject: + case FixKind::SpecifyClosureParameterType: case FixKind::SpecifyClosureReturnType: case FixKind::AddQualifierToAccessTopLevelName: llvm_unreachable("handled elsewhere"); @@ -9694,14 +9714,21 @@ ConstraintSystem::addKeyPathApplicationRootConstraint(Type root, ConstraintLocat path[0].getKind() == ConstraintLocator::SubscriptMember) || (path.size() == 2 && path[1].getKind() == ConstraintLocator::KeyPathDynamicMember)); + auto indexTuple = dyn_cast(subscript->getIndex()); - if (!indexTuple || indexTuple->getNumElements() != 1) - return; - - auto keyPathExpr = dyn_cast(indexTuple->getElement(0)); + auto indexParen = dyn_cast(subscript->getIndex()); + // If a keypath subscript is used without the expected `keyPath:` label, + // continue with type-checking when attempting fixes so that it gets caught + // by the argument label checking. In such cases, the KeyPathExpr is contained + // in a ParenExpr, instead of a TupleExpr. + assert(((indexTuple && indexTuple->getNumElements() == 1) || indexParen) && + "Expected KeyPathExpr to be in either TupleExpr or ParenExpr"); + + auto keyPathExpr = dyn_cast( + indexTuple ? indexTuple->getElement(0) : indexParen->getSubExpr()); if (!keyPathExpr) return; - + auto typeVar = getType(keyPathExpr)->getAs(); if (!typeVar) return; diff --git a/lib/Sema/ConstraintGraph.cpp b/lib/Sema/ConstraintGraph.cpp index cae8cc158d758..1bbe186cc4068 100644 --- a/lib/Sema/ConstraintGraph.cpp +++ b/lib/Sema/ConstraintGraph.cpp @@ -1126,6 +1126,10 @@ bool ConstraintGraph::contractEdges() { if (isParamBindingConstraint && tyvar1->getImpl().canBindToInOut()) { bool isNotContractable = true; if (auto bindings = CS.getPotentialBindings(tyvar1)) { + // Holes can't be contracted. + if (bindings.IsHole) + continue; + for (auto &binding : bindings.Bindings) { auto type = binding.BindingType; isNotContractable = type.findIf([&](Type nestedType) -> bool { diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 83d8005334a98..c30c0a1f210a5 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -300,6 +300,10 @@ class TypeVariableType::Implementation { /// Determine whether this type variable represents a closure type. bool isClosureType() const; + /// Determine whether this type variable represents one of the + /// parameter types associated with a closure. + bool isClosureParameterType() const; + /// Determine whether this type variable represents a closure result type. bool isClosureResultType() const; diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 956253ba2dc02..6ddb39a07e68c 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -90,6 +90,14 @@ bool TypeVariableType::Implementation::isClosureType() const { return isa(locator->getAnchor()) && locator->getPath().empty(); } +bool TypeVariableType::Implementation::isClosureParameterType() const { + if (!(locator && locator->getAnchor())) + return false; + + return isa(locator->getAnchor()) && + locator->isLastElement(); +} + bool TypeVariableType::Implementation::isClosureResultType() const { if (!(locator && locator->getAnchor())) return false; diff --git a/stdlib/private/StdlibCollectionUnittest/CMakeLists.txt b/stdlib/private/StdlibCollectionUnittest/CMakeLists.txt index 0efaf5ab37f0b..451a7d296e940 100644 --- a/stdlib/private/StdlibCollectionUnittest/CMakeLists.txt +++ b/stdlib/private/StdlibCollectionUnittest/CMakeLists.txt @@ -12,7 +12,6 @@ add_swift_target_library(swiftStdlibCollectionUnittest ${SWIFT_STDLIB_LIBRARY_BU CheckRangeReplaceableSliceType.swift CheckSequenceInstance.swift CheckSequenceType.swift - COWLoggingArray.swift LoggingWrappers.swift MinimalCollections.swift RangeSelection.swift diff --git a/stdlib/private/StdlibCollectionUnittest/COWLoggingArray.swift b/stdlib/private/StdlibCollectionUnittest/COWLoggingArray.swift deleted file mode 100644 index 70d89007e3daa..0000000000000 --- a/stdlib/private/StdlibCollectionUnittest/COWLoggingArray.swift +++ /dev/null @@ -1,123 +0,0 @@ -import StdlibUnittest - -fileprivate var COWLoggingArray_CopyCount = 0 - -public func expectNoCopyOnWrite( - _ elements: [T], - _ message: @autoclosure () -> String = "", - stackTrace: SourceLocStack = SourceLocStack(), - showFrame: Bool = true, - file: String = #file, - line: UInt = #line, - _ body: (inout COWLoggingArray) -> Void -) { - let copyCountBeforeBody = COWLoggingArray_CopyCount - var loggingArray = COWLoggingArray(elements) - body(&loggingArray) - expectEqual(copyCountBeforeBody, COWLoggingArray_CopyCount, message(), - stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), - showFrame: false) -} - -public struct COWLoggingArray { - var storage: Storage - - class Storage { - var buffer: UnsafeMutableBufferPointer - var count: Int - var capacity: Int { - buffer.count - } - - init(capacity: Int) { - self.buffer = .allocate(capacity: capacity) - self.count = 0 - } - - deinit { - buffer.baseAddress!.deinitialize(count: count) - buffer.deallocate() - } - - func cloned(capacity: Int? = nil) -> Storage { - let newCapacity = Swift.max(capacity ?? self.capacity, self.capacity) - let newStorage = Storage(capacity: newCapacity) - newStorage.buffer.baseAddress! - .initialize(from: buffer.baseAddress!, count: count) - newStorage.count = count - return newStorage - } - } - - mutating func _makeUnique() { - if !isKnownUniquelyReferenced(&storage) { - storage = storage.cloned() - COWLoggingArray_CopyCount += 1 - } - } -} - -extension COWLoggingArray: RandomAccessCollection, RangeReplaceableCollection, - MutableCollection, ExpressibleByArrayLiteral -{ - public var count: Int { storage.count } - public var startIndex: Int { 0 } - public var endIndex: Int { count } - - public subscript(i: Int) -> Element { - get { - storage.buffer[i] - } - set { - _makeUnique() - storage.buffer[i] = newValue - } - } - - public init() { - storage = Storage(capacity: 10) - } - - public mutating func reserveCapacity(_ n: Int) { - if !isKnownUniquelyReferenced(&storage) { - COWLoggingArray_CopyCount += 1 - storage = storage.cloned(capacity: n) - } else if count < n { - storage = storage.cloned(capacity: n) - } - } - - public mutating func replaceSubrange(_ subrange: Range, with newElements: C) - where C : Collection, Element == C.Element - { - _makeUnique() - let newCount = (count - subrange.count) + newElements.count - if newCount > storage.capacity { - storage = storage.cloned(capacity: newCount) - } - - let startOfSubrange = storage.buffer.baseAddress! + subrange.lowerBound - let endOfSubrange = startOfSubrange + subrange.count - let endOfNewElements = startOfSubrange + newElements.count - let countAfterSubrange = count - subrange.upperBound - - // clear out old elements - startOfSubrange.deinitialize(count: subrange.count) - - // move elements above subrange - endOfNewElements.moveInitialize(from: endOfSubrange, count: countAfterSubrange) - - // assign new elements - for (pointer, element) in zip(startOfSubrange..., newElements) { - pointer.initialize(to: element) - } - - // update count - storage.count = newCount - } - - public init(arrayLiteral elements: Element...) { - storage = Storage(capacity: elements.count) - replaceSubrange(0..<0, with: elements) - } -} diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt index 95ee7f07826a5..942f14939c439 100644 --- a/stdlib/public/core/CMakeLists.txt +++ b/stdlib/public/core/CMakeLists.txt @@ -207,13 +207,10 @@ set(SWIFTLIB_SOURCES Availability.swift CollectionDifference.swift CollectionOfOne.swift - DiscontiguousSlice.swift Diffing.swift Mirror.swift PlaygroundDisplay.swift CommandLine.swift - RangeSet.swift - RangeSetStorage.swift SliceBuffer.swift SIMDVector.swift UnfoldSequence.swift diff --git a/stdlib/public/core/Codable.swift b/stdlib/public/core/Codable.swift index fbadc5c3f0181..4b7fa1abea676 100644 --- a/stdlib/public/core/Codable.swift +++ b/stdlib/public/core/Codable.swift @@ -498,9 +498,8 @@ public struct KeyedEncodingContainer : { public typealias Key = K - /// The container for the concrete encoder. The type is _*Base so that it's - /// generic on the key type. - internal var _box: _KeyedEncodingContainerBase + /// The container for the concrete encoder. + internal var _box: _KeyedEncodingContainerBase /// Creates a new instance with the given container. /// @@ -1467,9 +1466,8 @@ public struct KeyedDecodingContainer : { public typealias Key = K - /// The container for the concrete decoder. The type is _*Base so that it's - /// generic on the key type. - internal var _box: _KeyedDecodingContainerBase + /// The container for the concrete decoder. + internal var _box: _KeyedDecodingContainerBase /// Creates a new instance with the given container. /// @@ -1492,7 +1490,7 @@ public struct KeyedDecodingContainer : /// which are not convertible to one another. This should report all keys /// present which are convertible to the requested type. public var allKeys: [Key] { - return _box.allKeys + return _box.allKeys as! [Key] } /// Returns a Boolean value indicating whether the decoder contains a value @@ -3454,7 +3452,7 @@ extension DecodingError { // Keyed Encoding Container Implementations //===----------------------------------------------------------------------===// -internal class _KeyedEncodingContainerBase { +internal class _KeyedEncodingContainerBase { internal init(){} deinit {} @@ -3464,149 +3462,149 @@ internal class _KeyedEncodingContainerBase { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeNil(forKey key: Key) throws { + internal func encodeNil(forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encode(_ value: Bool, forKey key: Key) throws { + internal func encode(_ value: Bool, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encode(_ value: String, forKey key: Key) throws { + internal func encode(_ value: String, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encode(_ value: Double, forKey key: Key) throws { + internal func encode(_ value: Double, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encode(_ value: Float, forKey key: Key) throws { + internal func encode(_ value: Float, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encode(_ value: Int, forKey key: Key) throws { + internal func encode(_ value: Int, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encode(_ value: Int8, forKey key: Key) throws { + internal func encode(_ value: Int8, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encode(_ value: Int16, forKey key: Key) throws { + internal func encode(_ value: Int16, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encode(_ value: Int32, forKey key: Key) throws { + internal func encode(_ value: Int32, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encode(_ value: Int64, forKey key: Key) throws { + internal func encode(_ value: Int64, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encode(_ value: UInt, forKey key: Key) throws { + internal func encode(_ value: UInt, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encode(_ value: UInt8, forKey key: Key) throws { + internal func encode(_ value: UInt8, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encode(_ value: UInt16, forKey key: Key) throws { + internal func encode(_ value: UInt16, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encode(_ value: UInt32, forKey key: Key) throws { + internal func encode(_ value: UInt32, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encode(_ value: UInt64, forKey key: Key) throws { + internal func encode(_ value: UInt64, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encode(_ value: T, forKey key: Key) throws { + internal func encode(_ value: T, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeConditional( + internal func encodeConditional( _ object: T, - forKey key: Key + forKey key: K ) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeIfPresent(_ value: Bool?, forKey key: Key) throws { + internal func encodeIfPresent(_ value: Bool?, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeIfPresent(_ value: String?, forKey key: Key) throws { + internal func encodeIfPresent(_ value: String?, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeIfPresent(_ value: Double?, forKey key: Key) throws { + internal func encodeIfPresent(_ value: Double?, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeIfPresent(_ value: Float?, forKey key: Key) throws { + internal func encodeIfPresent(_ value: Float?, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeIfPresent(_ value: Int?, forKey key: Key) throws { + internal func encodeIfPresent(_ value: Int?, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeIfPresent(_ value: Int8?, forKey key: Key) throws { + internal func encodeIfPresent(_ value: Int8?, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeIfPresent(_ value: Int16?, forKey key: Key) throws { + internal func encodeIfPresent(_ value: Int16?, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeIfPresent(_ value: Int32?, forKey key: Key) throws { + internal func encodeIfPresent(_ value: Int32?, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeIfPresent(_ value: Int64?, forKey key: Key) throws { + internal func encodeIfPresent(_ value: Int64?, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeIfPresent(_ value: UInt?, forKey key: Key) throws { + internal func encodeIfPresent(_ value: UInt?, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeIfPresent(_ value: UInt8?, forKey key: Key) throws { + internal func encodeIfPresent(_ value: UInt8?, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeIfPresent(_ value: UInt16?, forKey key: Key) throws { + internal func encodeIfPresent(_ value: UInt16?, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeIfPresent(_ value: UInt32?, forKey key: Key) throws { + internal func encodeIfPresent(_ value: UInt32?, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeIfPresent(_ value: UInt64?, forKey key: Key) throws { + internal func encodeIfPresent(_ value: UInt64?, forKey key: K) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func encodeIfPresent( + internal func encodeIfPresent( _ value: T?, - forKey key: Key + forKey key: K ) throws { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func nestedContainer( + internal func nestedContainer( keyedBy keyType: NestedKey.Type, - forKey key: Key + forKey key: K ) -> KeyedEncodingContainer { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func nestedUnkeyedContainer( - forKey key: Key + internal func nestedUnkeyedContainer( + forKey key: K ) -> UnkeyedEncodingContainer { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } @@ -3615,14 +3613,14 @@ internal class _KeyedEncodingContainerBase { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } - internal func superEncoder(forKey key: Key) -> Encoder { + internal func superEncoder(forKey key: K) -> Encoder { fatalError("_KeyedEncodingContainerBase cannot be used directly.") } } internal final class _KeyedEncodingContainerBox< Concrete: KeyedEncodingContainerProtocol ->: _KeyedEncodingContainerBase { +>: _KeyedEncodingContainerBase { typealias Key = Concrete.Key internal var concrete: Concrete @@ -3635,195 +3633,263 @@ internal final class _KeyedEncodingContainerBox< return concrete.codingPath } - override internal func encodeNil(forKey key: Key) throws { + override internal func encodeNil(forKey key: K) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeNil(forKey: key) } - override internal func encode(_ value: Bool, forKey key: Key) throws { + override internal func encode(_ value: Bool, forKey key: K) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encode(value, forKey: key) } - override internal func encode(_ value: String, forKey key: Key) throws { + override internal func encode(_ value: String, forKey key: K) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encode(value, forKey: key) } - override internal func encode(_ value: Double, forKey key: Key) throws { + override internal func encode(_ value: Double, forKey key: K) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encode(value, forKey: key) } - override internal func encode(_ value: Float, forKey key: Key) throws { + override internal func encode(_ value: Float, forKey key: K) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encode(value, forKey: key) } - override internal func encode(_ value: Int, forKey key: Key) throws { + override internal func encode(_ value: Int, forKey key: K) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encode(value, forKey: key) } - override internal func encode(_ value: Int8, forKey key: Key) throws { + override internal func encode(_ value: Int8, forKey key: K) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encode(value, forKey: key) } - override internal func encode(_ value: Int16, forKey key: Key) throws { + override internal func encode(_ value: Int16, forKey key: K) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encode(value, forKey: key) } - override internal func encode(_ value: Int32, forKey key: Key) throws { + override internal func encode(_ value: Int32, forKey key: K) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encode(value, forKey: key) } - override internal func encode(_ value: Int64, forKey key: Key) throws { + override internal func encode(_ value: Int64, forKey key: K) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encode(value, forKey: key) } - override internal func encode(_ value: UInt, forKey key: Key) throws { + override internal func encode(_ value: UInt, forKey key: K) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encode(value, forKey: key) } - override internal func encode(_ value: UInt8, forKey key: Key) throws { + override internal func encode(_ value: UInt8, forKey key: K) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encode(value, forKey: key) } - override internal func encode(_ value: UInt16, forKey key: Key) throws { + override internal func encode(_ value: UInt16, forKey key: K) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encode(value, forKey: key) } - override internal func encode(_ value: UInt32, forKey key: Key) throws { + override internal func encode(_ value: UInt32, forKey key: K) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encode(value, forKey: key) } - override internal func encode(_ value: UInt64, forKey key: Key) throws { + override internal func encode(_ value: UInt64, forKey key: K) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encode(value, forKey: key) } - override internal func encode( + override internal func encode( _ value: T, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encode(value, forKey: key) } - override internal func encodeConditional( + override internal func encodeConditional( _ object: T, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeConditional(object, forKey: key) } - override internal func encodeIfPresent( + override internal func encodeIfPresent( _ value: Bool?, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeIfPresent(value, forKey: key) } - override internal func encodeIfPresent( + override internal func encodeIfPresent( _ value: String?, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeIfPresent(value, forKey: key) } - override internal func encodeIfPresent( + override internal func encodeIfPresent( _ value: Double?, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeIfPresent(value, forKey: key) } - override internal func encodeIfPresent( + override internal func encodeIfPresent( _ value: Float?, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeIfPresent(value, forKey: key) } - override internal func encodeIfPresent( + override internal func encodeIfPresent( _ value: Int?, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeIfPresent(value, forKey: key) } - override internal func encodeIfPresent( + override internal func encodeIfPresent( _ value: Int8?, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeIfPresent(value, forKey: key) } - override internal func encodeIfPresent( + override internal func encodeIfPresent( _ value: Int16?, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeIfPresent(value, forKey: key) } - override internal func encodeIfPresent( + override internal func encodeIfPresent( _ value: Int32?, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeIfPresent(value, forKey: key) } - override internal func encodeIfPresent( + override internal func encodeIfPresent( _ value: Int64?, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeIfPresent(value, forKey: key) } - override internal func encodeIfPresent( + override internal func encodeIfPresent( _ value: UInt?, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeIfPresent(value, forKey: key) } - override internal func encodeIfPresent( + override internal func encodeIfPresent( _ value: UInt8?, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeIfPresent(value, forKey: key) } - override internal func encodeIfPresent( + override internal func encodeIfPresent( _ value: UInt16?, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeIfPresent(value, forKey: key) } - override internal func encodeIfPresent( + override internal func encodeIfPresent( _ value: UInt32?, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeIfPresent(value, forKey: key) } - override internal func encodeIfPresent( + override internal func encodeIfPresent( _ value: UInt64?, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeIfPresent(value, forKey: key) } - override internal func encodeIfPresent( + override internal func encodeIfPresent( _ value: T?, - forKey key: Key + forKey key: K ) throws { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) try concrete.encodeIfPresent(value, forKey: key) } - override internal func nestedContainer( + override internal func nestedContainer( keyedBy keyType: NestedKey.Type, - forKey key: Key + forKey key: K ) -> KeyedEncodingContainer { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return concrete.nestedContainer(keyedBy: NestedKey.self, forKey: key) } - override internal func nestedUnkeyedContainer( - forKey key: Key + override internal func nestedUnkeyedContainer( + forKey key: K ) -> UnkeyedEncodingContainer { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return concrete.nestedUnkeyedContainer(forKey: key) } @@ -3831,12 +3897,14 @@ internal final class _KeyedEncodingContainerBox< return concrete.superEncoder() } - override internal func superEncoder(forKey key: Key) -> Encoder { + override internal func superEncoder(forKey key: K) -> Encoder { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return concrete.superEncoder(forKey: key) } } -internal class _KeyedDecodingContainerBase { +internal class _KeyedDecodingContainerBase { internal init(){} deinit {} @@ -3845,237 +3913,237 @@ internal class _KeyedDecodingContainerBase { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal var allKeys: [Key] { + internal var allKeys: [CodingKey] { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func contains(_ key: Key) -> Bool { + internal func contains(_ key: K) -> Bool { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeNil(forKey key: Key) throws -> Bool { + internal func decodeNil(forKey key: K) throws -> Bool { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decode( + internal func decode( _ type: Bool.Type, - forKey key: Key + forKey key: K ) throws -> Bool { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decode( + internal func decode( _ type: String.Type, - forKey key: Key + forKey key: K ) throws -> String { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decode( + internal func decode( _ type: Double.Type, - forKey key: Key + forKey key: K ) throws -> Double { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decode( + internal func decode( _ type: Float.Type, - forKey key: Key + forKey key: K ) throws -> Float { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decode( + internal func decode( _ type: Int.Type, - forKey key: Key + forKey key: K ) throws -> Int { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decode( + internal func decode( _ type: Int8.Type, - forKey key: Key + forKey key: K ) throws -> Int8 { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decode( + internal func decode( _ type: Int16.Type, - forKey key: Key + forKey key: K ) throws -> Int16 { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decode( + internal func decode( _ type: Int32.Type, - forKey key: Key + forKey key: K ) throws -> Int32 { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decode( + internal func decode( _ type: Int64.Type, - forKey key: Key + forKey key: K ) throws -> Int64 { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decode( + internal func decode( _ type: UInt.Type, - forKey key: Key + forKey key: K ) throws -> UInt { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decode( + internal func decode( _ type: UInt8.Type, - forKey key: Key + forKey key: K ) throws -> UInt8 { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decode( + internal func decode( _ type: UInt16.Type, - forKey key: Key + forKey key: K ) throws -> UInt16 { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decode( + internal func decode( _ type: UInt32.Type, - forKey key: Key + forKey key: K ) throws -> UInt32 { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decode( + internal func decode( _ type: UInt64.Type, - forKey key: Key + forKey key: K ) throws -> UInt64 { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decode( + internal func decode( _ type: T.Type, - forKey key: Key + forKey key: K ) throws -> T { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeIfPresent( + internal func decodeIfPresent( _ type: Bool.Type, - forKey key: Key + forKey key: K ) throws -> Bool? { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeIfPresent( + internal func decodeIfPresent( _ type: String.Type, - forKey key: Key + forKey key: K ) throws -> String? { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeIfPresent( + internal func decodeIfPresent( _ type: Double.Type, - forKey key: Key + forKey key: K ) throws -> Double? { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeIfPresent( + internal func decodeIfPresent( _ type: Float.Type, - forKey key: Key + forKey key: K ) throws -> Float? { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeIfPresent( + internal func decodeIfPresent( _ type: Int.Type, - forKey key: Key + forKey key: K ) throws -> Int? { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeIfPresent( + internal func decodeIfPresent( _ type: Int8.Type, - forKey key: Key + forKey key: K ) throws -> Int8? { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeIfPresent( + internal func decodeIfPresent( _ type: Int16.Type, - forKey key: Key + forKey key: K ) throws -> Int16? { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeIfPresent( + internal func decodeIfPresent( _ type: Int32.Type, - forKey key: Key + forKey key: K ) throws -> Int32? { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeIfPresent( + internal func decodeIfPresent( _ type: Int64.Type, - forKey key: Key + forKey key: K ) throws -> Int64? { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeIfPresent( + internal func decodeIfPresent( _ type: UInt.Type, - forKey key: Key + forKey key: K ) throws -> UInt? { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeIfPresent( + internal func decodeIfPresent( _ type: UInt8.Type, - forKey key: Key + forKey key: K ) throws -> UInt8? { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeIfPresent( + internal func decodeIfPresent( _ type: UInt16.Type, - forKey key: Key + forKey key: K ) throws -> UInt16? { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeIfPresent( + internal func decodeIfPresent( _ type: UInt32.Type, - forKey key: Key + forKey key: K ) throws -> UInt32? { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeIfPresent( + internal func decodeIfPresent( _ type: UInt64.Type, - forKey key: Key + forKey key: K ) throws -> UInt64? { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func decodeIfPresent( + internal func decodeIfPresent( _ type: T.Type, - forKey key: Key + forKey key: K ) throws -> T? { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func nestedContainer( + internal func nestedContainer( keyedBy type: NestedKey.Type, - forKey key: Key + forKey key: K ) throws -> KeyedDecodingContainer { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func nestedUnkeyedContainer( - forKey key: Key + internal func nestedUnkeyedContainer( + forKey key: K ) throws -> UnkeyedDecodingContainer { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } @@ -4084,14 +4152,14 @@ internal class _KeyedDecodingContainerBase { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } - internal func superDecoder(forKey key: Key) throws -> Decoder { + internal func superDecoder(forKey key: K) throws -> Decoder { fatalError("_KeyedDecodingContainerBase cannot be used directly.") } } internal final class _KeyedDecodingContainerBox< Concrete: KeyedDecodingContainerProtocol ->: _KeyedDecodingContainerBase { +>: _KeyedDecodingContainerBase { typealias Key = Concrete.Key internal var concrete: Concrete @@ -4104,238 +4172,306 @@ internal final class _KeyedDecodingContainerBox< return concrete.codingPath } - override var allKeys: [Key] { + override var allKeys: [CodingKey] { return concrete.allKeys } - override internal func contains(_ key: Key) -> Bool { + override internal func contains(_ key: K) -> Bool { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return concrete.contains(key) } - override internal func decodeNil(forKey key: Key) throws -> Bool { + override internal func decodeNil(forKey key: K) throws -> Bool { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeNil(forKey: key) } - override internal func decode( + override internal func decode( _ type: Bool.Type, - forKey key: Key + forKey key: K ) throws -> Bool { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decode(Bool.self, forKey: key) } - override internal func decode( + override internal func decode( _ type: String.Type, - forKey key: Key + forKey key: K ) throws -> String { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decode(String.self, forKey: key) } - override internal func decode( + override internal func decode( _ type: Double.Type, - forKey key: Key + forKey key: K ) throws -> Double { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decode(Double.self, forKey: key) } - override internal func decode( + override internal func decode( _ type: Float.Type, - forKey key: Key + forKey key: K ) throws -> Float { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decode(Float.self, forKey: key) } - override internal func decode( + override internal func decode( _ type: Int.Type, - forKey key: Key + forKey key: K ) throws -> Int { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decode(Int.self, forKey: key) } - override internal func decode( + override internal func decode( _ type: Int8.Type, - forKey key: Key + forKey key: K ) throws -> Int8 { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decode(Int8.self, forKey: key) } - override internal func decode( + override internal func decode( _ type: Int16.Type, - forKey key: Key + forKey key: K ) throws -> Int16 { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decode(Int16.self, forKey: key) } - override internal func decode( + override internal func decode( _ type: Int32.Type, - forKey key: Key + forKey key: K ) throws -> Int32 { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decode(Int32.self, forKey: key) } - override internal func decode( + override internal func decode( _ type: Int64.Type, - forKey key: Key + forKey key: K ) throws -> Int64 { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decode(Int64.self, forKey: key) } - override internal func decode( + override internal func decode( _ type: UInt.Type, - forKey key: Key + forKey key: K ) throws -> UInt { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decode(UInt.self, forKey: key) } - override internal func decode( + override internal func decode( _ type: UInt8.Type, - forKey key: Key + forKey key: K ) throws -> UInt8 { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decode(UInt8.self, forKey: key) } - override internal func decode( + override internal func decode( _ type: UInt16.Type, - forKey key: Key + forKey key: K ) throws -> UInt16 { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decode(UInt16.self, forKey: key) } - override internal func decode( + override internal func decode( _ type: UInt32.Type, - forKey key: Key + forKey key: K ) throws -> UInt32 { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decode(UInt32.self, forKey: key) } - override internal func decode( + override internal func decode( _ type: UInt64.Type, - forKey key: Key + forKey key: K ) throws -> UInt64 { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decode(UInt64.self, forKey: key) } - override internal func decode( + override internal func decode( _ type: T.Type, - forKey key: Key + forKey key: K ) throws -> T { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decode(T.self, forKey: key) } - override internal func decodeIfPresent( + override internal func decodeIfPresent( _ type: Bool.Type, - forKey key: Key + forKey key: K ) throws -> Bool? { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeIfPresent(Bool.self, forKey: key) } - override internal func decodeIfPresent( + override internal func decodeIfPresent( _ type: String.Type, - forKey key: Key + forKey key: K ) throws -> String? { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeIfPresent(String.self, forKey: key) } - override internal func decodeIfPresent( + override internal func decodeIfPresent( _ type: Double.Type, - forKey key: Key + forKey key: K ) throws -> Double? { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeIfPresent(Double.self, forKey: key) } - override internal func decodeIfPresent( + override internal func decodeIfPresent( _ type: Float.Type, - forKey key: Key + forKey key: K ) throws -> Float? { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeIfPresent(Float.self, forKey: key) } - override internal func decodeIfPresent( + override internal func decodeIfPresent( _ type: Int.Type, - forKey key: Key + forKey key: K ) throws -> Int? { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeIfPresent(Int.self, forKey: key) } - override internal func decodeIfPresent( + override internal func decodeIfPresent( _ type: Int8.Type, - forKey key: Key + forKey key: K ) throws -> Int8? { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeIfPresent(Int8.self, forKey: key) } - override internal func decodeIfPresent( + override internal func decodeIfPresent( _ type: Int16.Type, - forKey key: Key + forKey key: K ) throws -> Int16? { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeIfPresent(Int16.self, forKey: key) } - override internal func decodeIfPresent( + override internal func decodeIfPresent( _ type: Int32.Type, - forKey key: Key + forKey key: K ) throws -> Int32? { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeIfPresent(Int32.self, forKey: key) } - override internal func decodeIfPresent( + override internal func decodeIfPresent( _ type: Int64.Type, - forKey key: Key + forKey key: K ) throws -> Int64? { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeIfPresent(Int64.self, forKey: key) } - override internal func decodeIfPresent( + override internal func decodeIfPresent( _ type: UInt.Type, - forKey key: Key + forKey key: K ) throws -> UInt? { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeIfPresent(UInt.self, forKey: key) } - override internal func decodeIfPresent( + override internal func decodeIfPresent( _ type: UInt8.Type, - forKey key: Key + forKey key: K ) throws -> UInt8? { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeIfPresent(UInt8.self, forKey: key) } - override internal func decodeIfPresent( + override internal func decodeIfPresent( _ type: UInt16.Type, - forKey key: Key + forKey key: K ) throws -> UInt16? { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeIfPresent(UInt16.self, forKey: key) } - override internal func decodeIfPresent( + override internal func decodeIfPresent( _ type: UInt32.Type, - forKey key: Key + forKey key: K ) throws -> UInt32? { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeIfPresent(UInt32.self, forKey: key) } - override internal func decodeIfPresent( + override internal func decodeIfPresent( _ type: UInt64.Type, - forKey key: Key + forKey key: K ) throws -> UInt64? { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeIfPresent(UInt64.self, forKey: key) } - override internal func decodeIfPresent( + override internal func decodeIfPresent( _ type: T.Type, - forKey key: Key + forKey key: K ) throws -> T? { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.decodeIfPresent(T.self, forKey: key) } - override internal func nestedContainer( + override internal func nestedContainer( keyedBy type: NestedKey.Type, - forKey key: Key + forKey key: K ) throws -> KeyedDecodingContainer { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.nestedContainer(keyedBy: NestedKey.self, forKey: key) } - override internal func nestedUnkeyedContainer( - forKey key: Key + override internal func nestedUnkeyedContainer( + forKey key: K ) throws -> UnkeyedDecodingContainer { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.nestedUnkeyedContainer(forKey: key) } @@ -4343,7 +4479,9 @@ internal final class _KeyedDecodingContainerBox< return try concrete.superDecoder() } - override internal func superDecoder(forKey key: Key) throws -> Decoder { + override internal func superDecoder(forKey key: K) throws -> Decoder { + assert(K.self == Key.self) + let key = unsafeBitCast(key, to: Key.self) return try concrete.superDecoder(forKey: key) } } diff --git a/stdlib/public/core/CollectionAlgorithms.swift b/stdlib/public/core/CollectionAlgorithms.swift index 8bb9bd46a102b..7d7e5467369c7 100644 --- a/stdlib/public/core/CollectionAlgorithms.swift +++ b/stdlib/public/core/CollectionAlgorithms.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2018 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 @@ -209,70 +209,6 @@ extension BidirectionalCollection where Element: Equatable { } } -//===----------------------------------------------------------------------===// -// subranges(where:) / subranges(of:) -//===----------------------------------------------------------------------===// - -extension Collection { - /// Returns the indices of all the elements that match the given predicate. - /// - /// For example, you can use this method to find all the places that a - /// vowel occurs in a string. - /// - /// let str = "Fresh cheese in a breeze" - /// let vowels: Set = ["a", "e", "i", "o", "u"] - /// let allTheVowels = str.subranges(where: { vowels.contains($0) }) - /// // str[allTheVowels].count == 9 - /// - /// - Parameter predicate: A closure that takes an element as its argument - /// and returns a Boolean value that indicates whether the passed element - /// represents a match. - /// - Returns: A set of the indices of the elements for which `predicate` - /// returns `true`. - /// - /// - Complexity: O(*n*), where *n* is the length of the collection. - @available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) - public func subranges(where predicate: (Element) throws -> Bool) rethrows - -> RangeSet - { - if isEmpty { return RangeSet() } - - var result = RangeSet() - var i = startIndex - while i != endIndex { - let next = index(after: i) - if try predicate(self[i]) { - result._append(i.. RangeSet { - subranges(where: { $0 == element }) - } -} - //===----------------------------------------------------------------------===// // partition(by:) //===----------------------------------------------------------------------===// @@ -433,81 +369,6 @@ extension MutableCollection where Self: BidirectionalCollection { } } -//===----------------------------------------------------------------------===// -// _indexedStablePartition / _partitioningIndex -//===----------------------------------------------------------------------===// - -extension MutableCollection { - /// Moves all elements at the indices satisfying `belongsInSecondPartition` - /// into a suffix of the collection, preserving their relative order, and - /// returns the start of the resulting suffix. - /// - /// - Complexity: O(*n* log *n*) where *n* is the number of elements. - /// - Precondition: - /// `n == distance(from: range.lowerBound, to: range.upperBound)` - internal mutating func _indexedStablePartition( - count n: Int, - range: Range, - by belongsInSecondPartition: (Index) throws-> Bool - ) rethrows -> Index { - if n == 0 { return range.lowerBound } - if n == 1 { - return try belongsInSecondPartition(range.lowerBound) - ? range.lowerBound - : range.upperBound - } - let h = n / 2, i = index(range.lowerBound, offsetBy: h) - let j = try _indexedStablePartition( - count: h, - range: range.lowerBound.. Bool - ) rethrows -> Index { - var n = count - var l = startIndex - - while n > 0 { - let half = n / 2 - let mid = index(l, offsetBy: half) - if try predicate(self[mid]) { - n = half - } else { - l = index(after: mid) - n -= half + 1 - } - } - return l - } -} - //===----------------------------------------------------------------------===// // shuffled()/shuffle() //===----------------------------------------------------------------------===// diff --git a/stdlib/public/core/DiscontiguousSlice.swift b/stdlib/public/core/DiscontiguousSlice.swift deleted file mode 100644 index eccd2c86e63dd..0000000000000 --- a/stdlib/public/core/DiscontiguousSlice.swift +++ /dev/null @@ -1,206 +0,0 @@ -//===--- DiscontiguousSlice.swift -----------------------------*- swift -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2020 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -/// A collection wrapper that provides access to the elements of a collection, -/// indexed by a set of indices. -@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) -@frozen -public struct DiscontiguousSlice { - /// The collection that the indexed collection wraps. - public var base: Base - - /// The set of subranges that are available through this discontiguous slice. - public var subranges: RangeSet -} - -@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) -extension DiscontiguousSlice { - /// A position in an `DiscontiguousSlice`. - @frozen - public struct Index: Comparable { - /// The index of the range that contains `base`. - internal var _rangeOffset: Int - - /// The position of this index in the base collection. - public var base: Base.Index - - public static func < (lhs: Index, rhs: Index) -> Bool { - lhs.base < rhs.base - } - } -} - -@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) -extension DiscontiguousSlice.Index: Hashable where Base.Index: Hashable {} - -@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) -extension DiscontiguousSlice: Collection { - public typealias SubSequence = Self - - public var startIndex: Index { - subranges.isEmpty - ? endIndex - : Index(_rangeOffset: 0, base: subranges._ranges[0].lowerBound) - } - - public var endIndex: Index { - Index(_rangeOffset: subranges._ranges.endIndex, base: base.endIndex) - } - - public func index(after i: Index) -> Index { - let nextIndex = base.index(after: i.base) - if subranges._ranges[i._rangeOffset].contains(nextIndex) { - return Index(_rangeOffset: i._rangeOffset, base: nextIndex) - } - - let nextOffset = i._rangeOffset + 1 - if nextOffset < subranges._ranges.endIndex { - return Index( - _rangeOffset: nextOffset, - base: subranges._ranges[nextOffset].lowerBound) - } else { - return endIndex - } - } - - public subscript(i: Index) -> Base.Element { - base[i.base] - } - - public subscript(bounds: Range) -> DiscontiguousSlice { - let baseBounds = bounds.lowerBound.base ..< bounds.upperBound.base - let subset = subranges.intersection(RangeSet(baseBounds)) - return DiscontiguousSlice(base: base, subranges: subset) - } -} - -@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) -extension DiscontiguousSlice { - public var count: Int { - var c = 0 - for range in subranges._ranges { - c += base.distance(from: range.lowerBound, to: range.upperBound) - } - return c - } - - public __consuming func _copyToContiguousArray() -> ContiguousArray { - var result: ContiguousArray = [] - for range in subranges._ranges { - result.append(contentsOf: base[range]) - } - return result - } -} - -@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) -extension DiscontiguousSlice: BidirectionalCollection - where Base: BidirectionalCollection -{ - public func index(before i: Index) -> Index { - _precondition(i != startIndex, "Can't move index before startIndex") - - if i == endIndex || i.base == subranges._ranges[i._rangeOffset].lowerBound { - let offset = i._rangeOffset - 1 - return Index( - _rangeOffset: offset, - base: base.index(before: subranges._ranges[offset].upperBound)) - } - - return Index( - _rangeOffset: i._rangeOffset, - base: base.index(before: i.base)) - } -} - -@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) -extension DiscontiguousSlice: MutableCollection where Base: MutableCollection { - public subscript(i: Index) -> Base.Element { - get { - base[i.base] - } - set { - base[i.base] = newValue - } - } -} - -// MARK: Subscripts - -extension Collection { - /// Accesses a view of this collection with the elements at the given - /// indices. - /// - /// - Parameter subranges: The indices of the elements to retrieve from this - /// collection. - /// - Returns: A collection of the elements at the positions in `subranges`. - /// - /// - Complexity: O(1) - @available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) - public subscript(subranges: RangeSet) -> DiscontiguousSlice { - DiscontiguousSlice(base: self, subranges: subranges) - } -} - -extension MutableCollection { - /// Accesses a mutable view of this collection with the elements at the - /// given indices. - /// - /// - Parameter subranges: The ranges of the elements to retrieve from this - /// collection. - /// - Returns: A collection of the elements at the positions in `subranges`. - /// - /// - Complexity: O(1) to access the elements, O(*m*) to mutate the - /// elements at the positions in `subranges`, where *m* is the number of - /// elements indicated by `subranges`. - @available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) - public subscript(subranges: RangeSet) -> DiscontiguousSlice { - get { - DiscontiguousSlice(base: self, subranges: subranges) - } - set { - for i in newValue.indices { - self[i.base] = newValue[i] - } - } - } -} - -extension Collection { - /// Returns a collection of the elements in this collection that are not - /// represented by the given range set. - /// - /// For example, this code sample finds the indices of all the vowel - /// characters in the string, and then retrieves a collection that omits - /// those characters. - /// - /// let str = "The rain in Spain stays mainly in the plain." - /// let vowels: Set = ["a", "e", "i", "o", "u"] - /// let vowelIndices = str.subranges(where: { vowels.contains($0) }) - /// - /// let disemvoweled = str.removingSubranges(vowelIndices) - /// print(String(disemvoweled)) - /// // Prints "Th rn n Spn stys mnly n th pln." - /// - /// - Parameter subranges: A range set representing the indices of the - /// elements to remove. - /// - Returns: A collection of the elements that are not in `subranges`. - /// - /// - Complexity: O(*n*), where *n* is the length of the collection. - @available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) - public func removingSubranges( - _ subranges: RangeSet - ) -> DiscontiguousSlice { - let inversion = subranges._inverted(within: self) - return self[inversion] - } -} diff --git a/stdlib/public/core/GroupInfo.json b/stdlib/public/core/GroupInfo.json index 1b9a209004e67..e08fa92d9fd03 100644 --- a/stdlib/public/core/GroupInfo.json +++ b/stdlib/public/core/GroupInfo.json @@ -70,8 +70,6 @@ "Sort.swift", "Range.swift", "ClosedRange.swift", - "RangeSet.swift", - "RangeSetStorage.swift", "CollectionOfOne.swift", "BridgingBuffer.swift", "Sequence.swift", @@ -98,7 +96,6 @@ "Filter.swift", "Reverse.swift", "Slice.swift", - "DiscontiguousSlice.swift", "DropWhile.swift", "PrefixWhile.swift", "LazyCollection.swift", diff --git a/stdlib/public/core/MutableCollection.swift b/stdlib/public/core/MutableCollection.swift index 3e335e6f9a775..3fdd4e6cdc85a 100644 --- a/stdlib/public/core/MutableCollection.swift +++ b/stdlib/public/core/MutableCollection.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// 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 @@ -267,157 +267,6 @@ extension MutableCollection { } } -//===----------------------------------------------------------------------===// -// moveSubranges(_:to:) -//===----------------------------------------------------------------------===// - -extension MutableCollection { - /// Moves the elements in the given subranges to just before the element at - /// the specified index. - /// - /// This example finds all the uppercase letters in the array and then - /// moves them to between `"i"` and `"j"`. - /// - /// var letters = Array("ABCdeFGhijkLMNOp") - /// let uppercaseRanges = letters.subranges(where: { $0.isUppercase }) - /// let rangeOfUppercase = letters.moveSubranges(uppercaseRanges, to: 10) - /// // String(letters) == "dehiABCFGLMNOjkp" - /// // rangeOfUppercase == 4..<13 - /// - /// - Parameters: - /// - subranges: The subranges of the elements to move. - /// - insertionPoint: The index to use as the destination of the elements. - /// - Returns: The new bounds of the moved elements. - /// - /// - Complexity: O(*n* log *n*) where *n* is the length of the collection. - @available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) - @discardableResult - public mutating func moveSubranges( - _ subranges: RangeSet, to insertionPoint: Index - ) -> Range { - let lowerCount = distance(from: startIndex, to: insertionPoint) - let upperCount = distance(from: insertionPoint, to: endIndex) - let start = _indexedStablePartition( - count: lowerCount, - range: startIndex.., - shiftingToStart middle: Index - ) -> Index { - var m = middle, s = subrange.lowerBound - let e = subrange.upperBound - - // Handle the trivial cases - if s == m { return e } - if m == e { return s } - - // We have two regions of possibly-unequal length that need to be - // exchanged. The return value of this method is going to be the - // position following that of the element that is currently last - // (element j). - // - // [a b c d e f g|h i j] or [a b c|d e f g h i j] - // ^ ^ ^ ^ ^ ^ - // s m e s m e - // - var ret = e // start with a known incorrect result. - while true { - // Exchange the leading elements of each region (up to the - // length of the shorter region). - // - // [a b c d e f g|h i j] or [a b c|d e f g h i j] - // ^^^^^ ^^^^^ ^^^^^ ^^^^^ - // [h i j d e f g|a b c] or [d e f|a b c g h i j] - // ^ ^ ^ ^ ^ ^ ^ ^ - // s s1 m m1/e s s1/m m1 e - // - let (s1, m1) = _swapNonemptySubrangePrefixes(s.., _ rhs: Range - ) -> (Index, Index) { - assert(!lhs.isEmpty) - assert(!rhs.isEmpty) - - var p = lhs.lowerBound - var q = rhs.lowerBound - repeat { - swapAt(p, q) - formIndex(after: &p) - formIndex(after: &q) - } while p != lhs.upperBound && q != rhs.upperBound - return (p, q) - } -} - // the legacy swap free function // /// Exchanges the values of the two arguments. diff --git a/stdlib/public/core/RangeReplaceableCollection.swift b/stdlib/public/core/RangeReplaceableCollection.swift index 0765d74f8e20a..ff520598bbde8 100644 --- a/stdlib/public/core/RangeReplaceableCollection.swift +++ b/stdlib/public/core/RangeReplaceableCollection.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// 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 @@ -1138,94 +1138,3 @@ extension RangeReplaceableCollection { self = try filter { try !shouldBeRemoved($0) } } } - -extension RangeReplaceableCollection { - /// Removes the elements at the given indices. - /// - /// For example, this code sample finds the indices of all the vowel - /// characters in the string, and then removes those characters. - /// - /// var str = "The rain in Spain stays mainly in the plain." - /// let vowels: Set = ["a", "e", "i", "o", "u"] - /// let vowelIndices = str.subranges(where: { vowels.contains($0) }) - /// - /// str.removeSubranges(vowelIndices) - /// // str == "Th rn n Spn stys mnly n th pln." - /// - /// - Parameter subranges: The indices of the elements to remove. - /// - /// - Complexity: O(*n*), where *n* is the length of the collection. - @available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) - public mutating func removeSubranges(_ subranges: RangeSet) { - guard !subranges.isEmpty else { - return - } - - let inversion = subranges._inverted(within: self) - var result = Self() - for range in inversion.ranges { - result.append(contentsOf: self[range]) - } - self = result - } -} - -extension MutableCollection where Self: RangeReplaceableCollection { - /// Removes the elements at the given indices. - /// - /// For example, this code sample finds the indices of all the negative - /// numbers in the array, and then removes those values. - /// - /// var numbers = [5, 7, -3, -8, 11, 2, -1, 6] - /// let negativeIndices = numbers.subranges(where: { $0 < 0 }) - /// - /// numbers.removeSubranges(negativeIndices) - /// // numbers == [5, 7, 11, 2, 6] - /// - /// - Parameter subranges: The indices of the elements to remove. - /// - /// - Complexity: O(*n*), where *n* is the length of the collection. - @available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) - public mutating func removeSubranges(_ subranges: RangeSet) { - guard let firstRange = subranges.ranges.first else { - return - } - - var endOfElementsToKeep = firstRange.lowerBound - var firstUnprocessed = firstRange.upperBound - - // This performs a half-stable partition based on the ranges in - // `indices`. At all times, the collection is divided into three - // regions: - // - // - `self[.. { - internal var _ranges = _RangeSetStorage() - - /// Creates an empty range set. - public init() {} - - /// Creates a range set containing the given range. - /// - /// - Parameter range: The range to use for the new range set. - public init(_ range: Range) { - if !range.isEmpty { - self._ranges = _RangeSetStorage(range) - } - } - - /// Creates a range set containing the values in the given ranges. - /// - /// Any empty ranges in `ranges` are ignored, and non-empty ranges are merged - /// to eliminate any overlaps. As such, the `ranges` collection in the - /// resulting range set may not be equivalent to the sequence of ranges - /// passed to this initializer. - /// - /// - Parameter ranges: The ranges to use for the new range set. - public init(_ ranges: S) where S.Element == Range { - for range in ranges { - insert(contentsOf: range) - } - } - - /// Checks the invariants of `_ranges`. - /// - /// The ranges stored by a range set are never empty, never overlap, - /// and are always stored in ascending order when comparing their lower - /// or upper bounds. In addition to not overlapping, no two consecutive - /// ranges share an upper and lower bound — `[0..<5, 5..<10]` is ill-formed, - /// and would instead be represented as `[0..<10]`. - internal func _checkInvariants() { - for (a, b) in zip(ranges, ranges.dropFirst()) { - _debugPrecondition(!a.isEmpty && !b.isEmpty, "Empty range in range set") - _debugPrecondition( - a.upperBound < b.lowerBound, - "Out of order/overlapping ranges in range set") - } - } - - /// Creates a new range set from `ranges`, which satisfies the range set - /// invariants. - internal init(_orderedRanges ranges: [Range]) { - self._ranges = _RangeSetStorage(ranges) - _checkInvariants() - } - - /// A Boolean value indicating whether the range set is empty. - public var isEmpty: Bool { - _ranges.isEmpty - } - - /// Returns a Boolean value indicating whether the given value is - /// contained by the ranges in the range set. - /// - /// - Parameter value: The value to look for in the range set. - /// - Returns: `true` if `value` is contained by a range in the range set; - /// otherwise, `false`. - /// - /// - Complexity: O(log *n*), where *n* is the number of ranges in the - /// range set. - public func contains(_ value: Bound) -> Bool { - let i = _ranges._partitioningIndex { $0.upperBound > value } - return i == _ranges.endIndex - ? false - : _ranges[i].lowerBound <= value - } - - /// Returns a range indicating the existing ranges that `range` overlaps - /// with. - /// - /// For example, if `self` is `[0..<5, 10..<15, 20..<25, 30..<35]`, then: - /// - /// - `_indicesOfRange(12..<14) == 1..<2` - /// - `_indicesOfRange(12..<19) == 1..<2` - /// - `_indicesOfRange(17..<19) == 2..<2` - /// - `_indicesOfRange(12..<22) == 1..<3` - internal func _indicesOfRange(_ range: Range) -> Range { - _precondition(!range.isEmpty) - _precondition(!_ranges.isEmpty) - _precondition(range.lowerBound <= _ranges.last!.upperBound) - _precondition(range.upperBound >= _ranges.first!.lowerBound) - - // The beginning index for the position of `range` is the first range - // with an upper bound larger than `range`'s lower bound. The range - // at this position may or may not overlap `range`. - let beginningIndex = _ranges - ._partitioningIndex { $0.upperBound >= range.lowerBound } - - // The ending index for `range` is the first range with a lower bound - // greater than `range`'s upper bound. If this is the same as - // `beginningIndex`, than `range` doesn't overlap any of the existing - // ranges. If this is `ranges.endIndex`, then `range` overlaps the - // rest of the ranges. Otherwise, `range` overlaps one or - // more ranges in the set. - let endingIndex = _ranges[beginningIndex...] - ._partitioningIndex { $0.lowerBound > range.upperBound } - - return beginningIndex ..< endingIndex - } - - /// Inserts a non-empty range that is known to be greater than all the - /// elements in the set so far. - /// - /// - Precondition: The range set must be empty, or else - /// `ranges.last!.upperBound <= range.lowerBound`. - /// - Precondition: `range` must not be empty. - internal mutating func _append(_ range: Range) { - _precondition(_ranges.isEmpty - || _ranges.last!.upperBound <= range.lowerBound) - _precondition(!range.isEmpty) - if _ranges.isEmpty { - _ranges.append(range) - } else if _ranges.last!.upperBound == range.lowerBound { - _ranges[_ranges.count - 1] = - _ranges[_ranges.count - 1].lowerBound ..< range.upperBound - } else { - _ranges.append(range) - } - } - - /// Inserts the given range into the range set. - /// - /// - Parameter range: The range to insert into the set. - /// - /// - Complexity: O(*n*), where *n* is the number of ranges in the range - /// set. - public mutating func insert(contentsOf range: Range) { - // Shortcuts for the (literal) edge cases - if range.isEmpty { return } - guard !_ranges.isEmpty else { - _ranges.append(range) - return - } - guard range.lowerBound < _ranges.last!.upperBound else { - _append(range) - return - } - guard range.upperBound >= _ranges.first!.lowerBound else { - _ranges.insert(range, at: 0) - return - } - - let indices = _indicesOfRange(range) - - // Non-overlapping is a simple insertion. - guard !indices.isEmpty else { - _ranges.insert(range, at: indices.lowerBound) - return - } - - // Find the lower and upper bounds of the overlapping ranges. - let newLowerBound = Swift.min( - _ranges[indices.lowerBound].lowerBound, - range.lowerBound) - let newUpperBound = Swift.max( - _ranges[indices.upperBound - 1].upperBound, - range.upperBound) - _ranges.replaceSubrange( - indices, - with: CollectionOfOne(newLowerBound..) { - // Shortcuts for the (literal) edge cases - if range.isEmpty - || _ranges.isEmpty - || range.lowerBound >= _ranges.last!.upperBound - || range.upperBound < _ranges.first!.lowerBound - { return } - - let indices = _indicesOfRange(range) - - // No actual overlap, nothing to remove. - if indices.isEmpty { return } - - let overlapsLowerBound = - range.lowerBound > _ranges[indices.lowerBound].lowerBound - let overlapsUpperBound = - range.upperBound < _ranges[indices.upperBound - 1].upperBound - - switch (overlapsLowerBound, overlapsUpperBound) { - case (false, false): - _ranges.removeSubrange(indices) - case (false, true): - let newRange = - range.upperBound..<_ranges[indices.upperBound - 1].upperBound - _ranges.replaceSubrange(indices, with: CollectionOfOne(newRange)) - case (true, false): - let newRange = _ranges[indices.lowerBound].lowerBound.. - - public var startIndex: Int { _ranges.startIndex } - public var endIndex: Int { _ranges.endIndex } - - public subscript(i: Int) -> Range { - _ranges[i] - } - } - - /// A collection of the ranges that make up the range set. - /// - /// The ranges that you access by using `ranges` never overlap, are never - /// empty, and are always in increasing order. - public var ranges: Ranges { - Ranges(_ranges: _ranges) - } -} - -// MARK: - Collection APIs - -@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) -extension RangeSet { - /// Creates a new range set containing ranges that contain only the - /// specified indices in the given collection. - /// - /// - Parameters: - /// - index: The index to include in the range set. `index` must be a - /// valid index of `collection` that isn't the collection's `endIndex`. - /// - collection: The collection that contains `index`. - @inlinable - public init(_ indices: S, within collection: C) - where S: Sequence, C: Collection, S.Element == C.Index, C.Index == Bound - { - self.init() - for i in indices { - self.insert(i, within: collection) - } - } - - /// Inserts a range that contains only the specified index into the range - /// set. - /// - /// - Parameters: - /// - index: The index to insert into the range set. `index` must be a - /// valid index of `collection` that isn't the collection's `endIndex`. - /// - collection: The collection that contains `index`. - /// - /// - Complexity: O(*n*), where *n* is the number of ranges in the range - /// set. - @inlinable - public mutating func insert(_ index: Bound, within collection: C) - where C: Collection, C.Index == Bound - { - insert(contentsOf: index ..< collection.index(after: index)) - } - - /// Removes the range that contains only the specified index from the range - /// set. - /// - /// - Parameters: - /// - index: The index to remove from the range set. `index` must be a - /// valid index of `collection` that isn't the collection's `endIndex`. - /// - collection: The collection that contains `index`. - /// - /// - Complexity: O(*n*), where *n* is the number of ranges in the range - /// set. - @inlinable - public mutating func remove(_ index: Bound, within collection: C) - where C: Collection, C.Index == Bound - { - remove(contentsOf: index ..< collection.index(after: index)) - } - - /// Returns a range set that represents all the elements in the given - /// collection that aren't represented by this range set. - /// - /// - Parameter collection: The collection that the range set is relative - /// to. - /// - Returns: A new range set that represents the elements in `collection` - /// that aren't represented by this range set. - /// - /// - Complexity: O(*n*), where *n* is the number of ranges in the range - /// set. - internal func _inverted(within collection: C) -> RangeSet - where C: Collection, C.Index == Bound - { - return _gaps( - boundedBy: collection.startIndex..) -> RangeSet { - guard !_ranges.isEmpty else { return RangeSet(bounds) } - guard let start = _ranges.firstIndex(where: { $0.lowerBound >= bounds.lowerBound }) - else { return RangeSet() } - guard let end = _ranges.lastIndex(where: { $0.upperBound <= bounds.upperBound }) - else { return RangeSet() } - - var result = RangeSet() - var low = bounds.lowerBound - for range in _ranges[start...end] { - result.insert(contentsOf: low..) { - for range in other._ranges { - insert(contentsOf: range) - } - } - - /// Removes the contents of this range set that aren't also in the given - /// range set. - /// - /// - Parameter other: A range set to intersect with. - public mutating func formIntersection(_ other: RangeSet) { - self = self.intersection(other) - } - - /// Removes the contents of this range set that are also in the given set - /// and adds the contents of the given set that are not already in this - /// range set. - /// - /// - Parameter other: A range set to perform a symmetric difference against. - public mutating func formSymmetricDifference( - _ other: __owned RangeSet - ) { - self = self.symmetricDifference(other) - } - - /// Removes the contents of the given range set from this range set. - /// - /// - Parameter other: A range set to subtract from this one. - public mutating func subtract(_ other: RangeSet) { - for range in other._ranges { - remove(contentsOf: range) - } - } - - /// Returns a new range set containing the contents of both this set and the - /// given set. - /// - /// - Parameter other: The range set to merge with this one. - /// - Returns: A new range set. - public __consuming func union( - _ other: __owned RangeSet - ) -> RangeSet { - var result = self - result.formUnion(other) - return result - } - - /// Returns a new range set containing the contents of both this set and the - /// given set. - /// - /// - Parameter other: The range set to merge with this one. - /// - Returns: A new range set. - public __consuming func intersection( - _ other: RangeSet - ) -> RangeSet { - var otherRangeIndex = 0 - var result: [Range] = [] - - // Considering these two range sets: - // - // self = [0..<5, 9..<14] - // other = [1..<3, 4..<6, 8..<12] - // - // `self.intersection(other)` looks like this, where x's cover the - // ranges in `self`, y's cover the ranges in `other`, and z's cover the - // resulting ranges: - // - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - // xxxxxxxxxxxxxxxxxxx__ xxxxxxxxxxxxxxxxxxx__ - // yyyyyyy__ yyyyyyy__ yyyyyyyyyyyyyyy__ - // zzzzzzz__ zzz__ zzzzzzzzzzz__ - // - // The same, but for `other.intersection(self)`: - // - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - // xxxxxxx__ xxxxxxx__ xxxxxxxxxxxxxxx__ - // yyyyyyyyyyyyyyyyyyy__ yyyyyyyyyyyyyyyyyyy__ - // zzzzzzz__ zzz__ zzzzzzzzzzz__ - - for currentRange in _ranges { - // Search forward in `other` until finding either an overlapping - // range or one that is strictly higher than this range. - while otherRangeIndex < other._ranges.endIndex && - other._ranges[otherRangeIndex].upperBound <= currentRange.lowerBound - { - otherRangeIndex += 1 - } - - // For each range in `other` that overlaps with the current range - // in `self`, append the intersection to the result. - while otherRangeIndex < other._ranges.endIndex && - other._ranges[otherRangeIndex].lowerBound < currentRange.upperBound - { - let lower = Swift.max( - other._ranges[otherRangeIndex].lowerBound, - currentRange.lowerBound) - let upper = Swift.min( - other._ranges[otherRangeIndex].upperBound, - currentRange.upperBound) - result.append(lower.. other._ranges[otherRangeIndex].upperBound - else { - break - } - otherRangeIndex += 1 - } - } - - return RangeSet(_orderedRanges: result) - } - - /// Returns a new range set representing the values in this range set or the - /// given range set, but not both. - /// - /// - Parameter other: The range set to find a symmetric difference with. - /// - Returns: A new range set. - public __consuming func symmetricDifference( - _ other: __owned RangeSet - ) -> RangeSet { - return union(other).subtracting(intersection(other)) - } - - /// Returns a new set containing the contents of this range set that are not - /// also in the given range set. - /// - /// - Parameter other: The range set to subtract. - /// - Returns: A new range set. - public func subtracting(_ other: RangeSet) -> RangeSet { - var result = self - result.subtract(other) - return result - } - - /// Returns a Boolean value that indicates whether this range set is a - /// subset of the given set. - /// - /// - Parameter other: A range set to compare against. - /// - Returns: `true` if this range set is a subset of `other`; - /// otherwise, `false`. - public func isSubset(of other: RangeSet) -> Bool { - self.intersection(other) == self - } - - /// Returns a Boolean value that indicates whether this range set is a - /// superset of the given set. - /// - /// - Parameter other: A range set to compare against. - /// - Returns: `true` if this range set is a superset of `other`; - /// otherwise, `false`. - public func isSuperset(of other: RangeSet) -> Bool { - other.isSubset(of: self) - } - - /// Returns a Boolean value that indicates whether this range set is a - /// strict subset of the given set. - /// - /// - Parameter other: A range set to compare against. - /// - Returns: `true` if this range set is a strict subset of `other`; - /// otherwise, `false`. - public func isStrictSubset(of other: RangeSet) -> Bool { - self != other && isSubset(of: other) - } - - /// Returns a Boolean value that indicates whether this range set is a - /// strict superset of the given set. - /// - /// - Parameter other: A range set to compare against. - /// - Returns: `true` if this range set is a strict superset of `other`; - /// otherwise, `false`. - public func isStrictSuperset(of other: RangeSet) -> Bool { - other.isStrictSubset(of: self) - } -} - -@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) -extension RangeSet: CustomStringConvertible { - public var description: String { - let rangesDescription = _ranges - .map { r in "\(r.lowerBound)..<\(r.upperBound)" } - .joined(separator: ", ") - return "RangeSet(\(rangesDescription))" - } -} - -/// A collection of two elements, to avoid heap allocation when calling -/// `replaceSubrange` with just two elements. -internal struct _Pair: RandomAccessCollection { - internal var pair: (first: Element, second: Element) - - internal init(_ first: Element, _ second: Element) { - self.pair = (first, second) - } - - internal var startIndex: Int { 0 } - internal var endIndex: Int { 2 } - - internal subscript(position: Int) -> Element { - get { - switch position { - case 0: return pair.first - case 1: return pair.second - default: _preconditionFailure("Index is out of range") - } - } - } -} diff --git a/stdlib/public/core/RangeSetStorage.swift b/stdlib/public/core/RangeSetStorage.swift deleted file mode 100644 index 078b398cf54b1..0000000000000 --- a/stdlib/public/core/RangeSetStorage.swift +++ /dev/null @@ -1,176 +0,0 @@ -//===----------------------------------------------------------*- swift -*-===// -// -// This source file is part of the Swift open source project -// -// Copyright (c) 2020 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// -//===----------------------------------------------------------------------===// - -/// Storage for a `RangeSet`. -/// -/// This is optimized to avoid allocating array storage for the common case of a -/// single range. The single range case is only attainable at initialization; -/// once added -internal struct _RangeSetStorage { - private enum _Storage { - case empty - case singleRange(Range) - case variadic([Range]) - } - - private var _storage: _Storage - - internal init() { - _storage = .empty - } - - internal init(_ range: Range) { - _storage = .singleRange(range) - } - - internal init(_ ranges: [Range]) { - _storage = .variadic(ranges) - } -} - -// _RangeSetStorage has custom Equatable (and therefore Hashable) -// conformance, since the same "value" can be represented by different -// storage structures. For example, `.empty` and `.variadic([])` are -// equivalent, but the synthesized conformance treats them as distinct. -// The same holds with the `singleRange` representation and `variadic` -// with a single-element array. - -extension _RangeSetStorage: Equatable { - internal static func == (lhs: _RangeSetStorage, rhs: _RangeSetStorage) -> Bool { - switch (lhs._storage, rhs._storage) { - case (.empty, .empty): - return true - case (.empty, .singleRange), (.singleRange, .empty): - return false - case let (.empty, .variadic(ranges)), - let (.variadic(ranges), .empty): - return ranges.isEmpty - - case let (.singleRange(lhs), .singleRange(rhs)): - return lhs == rhs - - case let (.singleRange(singleRange), .variadic(ranges)), - let (.variadic(ranges), .singleRange(singleRange)): - return ranges.count == 1 && - (ranges[0]) == singleRange - - case let (.variadic(lhsRanges), .variadic(rhsRanges)): - return lhsRanges == rhsRanges - } - } -} - -extension _RangeSetStorage: Hashable where T: Hashable { - internal func hash(into hasher: inout Hasher) { - for range in self { - hasher.combine(range) - } - } -} - -extension _RangeSetStorage: RandomAccessCollection, MutableCollection { - internal var startIndex: Int { 0 } - - internal var endIndex: Int { - switch _storage { - case .empty: return 0 - case .singleRange: return 1 - case let .variadic(ranges): return ranges.count - } - } - - internal subscript(i: Int) -> Range { - get { - switch _storage { - case .empty: - _preconditionFailure("Can't access elements of empty storage") - case let .singleRange(range): - _precondition(i == 0) - return range - case let .variadic(ranges): - return ranges[i] - } - } - set { - switch _storage { - case .empty: - _preconditionFailure("Can't access elements of empty storage") - case .singleRange: - _precondition(i == 0) - _storage = .singleRange(newValue) - case .variadic(var ranges): - // Temporarily set `_storage` to empty so that `ranges` - // remains uniquely referenced while mutating. - _storage = .empty - ranges[i] = newValue - _storage = .variadic(ranges) - } - } - } - - internal var count: Int { - switch _storage { - case .empty: return 0 - case .singleRange: return 1 - case let .variadic(ranges): return ranges.count - } - } -} - -extension _RangeSetStorage: RangeReplaceableCollection { - internal mutating func replaceSubrange( - _ subrange: Range, with newElements: C - ) where C : Collection, C.Element == Element { - switch _storage { - case .empty: - if !newElements.isEmpty { - _storage = .variadic(Array(newElements)) - } - - case let .singleRange(singleRange): - switch (subrange.isEmpty, newElements.isEmpty) { - case (false, true): - // Replacing the single range with an empty collection. - _storage = .empty - - case (false, false): - // Replacing the single range with a non-empty collection; - // promote to a variadic container. - _storage = .variadic(Array(newElements)) - - case (true, true): - // Inserting an empty collection; no-op. - break - - case (true, false): - // Inserting a non-empty collection either before or after - // the existing single element. - var ranges: [Range] - if subrange.lowerBound == 0 { - ranges = Array(newElements) - ranges.append(singleRange) - } else { - ranges = [singleRange] - ranges.append(contentsOf: newElements) - } - _storage = .variadic(ranges) - } - - case .variadic(var ranges): - // Temporarily set `_storage` to empty so that `ranges` - // remains uniquely referenced while mutating. - _storage = .empty - ranges.replaceSubrange(subrange, with: newElements) - _storage = .variadic(ranges) - } - } -} - diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index 2c224d3765875..9d6c7013bb5a0 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -4654,6 +4654,8 @@ static StringRef findAssociatedTypeName(const ProtocolDescriptor *protocol, return StringRef(); } +using AssociatedTypeWitness = std::atomic; + SWIFT_CC(swift) static MetadataResponse swift_getAssociatedTypeWitnessSlowImpl( @@ -4677,8 +4679,8 @@ swift_getAssociatedTypeWitnessSlowImpl( // Retrieve the witness. unsigned witnessIndex = assocType - reqBase; - auto *witnessAddr = &((const Metadata **)wtable)[witnessIndex]; - auto witness = *witnessAddr; + auto *witnessAddr = &((AssociatedTypeWitness*)wtable)[witnessIndex]; + auto witness = witnessAddr->load(std::memory_order_acquire); #if SWIFT_PTRAUTH uint16_t extraDiscriminator = assocType->Flags.getExtraDiscriminator(); @@ -4781,8 +4783,14 @@ swift_getAssociatedTypeWitnessSlowImpl( if (response.State == MetadataState::Complete) { // We pass type metadata around as unsigned pointers, but we sign them // in witness tables, which doesn't provide all that much extra security. - initAssociatedTypeProtocolWitness(witnessAddr, assocTypeMetadata, - *assocType); + auto valueToStore = assocTypeMetadata; +#if SWIFT_PTRAUTH + valueToStore = ptrauth_sign_unauthenticated(valueToStore, + swift_ptrauth_key_associated_type, + ptrauth_blend_discriminator(witnessAddr, + extraDiscriminator)); +#endif + witnessAddr->store(valueToStore, std::memory_order_release); } return response; @@ -4799,8 +4807,8 @@ swift::swift_getAssociatedTypeWitness(MetadataRequest request, // If the low bit of the witness is clear, it's already a metadata pointer. unsigned witnessIndex = assocType - reqBase; - auto *witnessAddr = &((const void* *)wtable)[witnessIndex]; - auto witness = *witnessAddr; + auto *witnessAddr = &((const AssociatedTypeWitness *)wtable)[witnessIndex]; + auto witness = witnessAddr->load(std::memory_order_acquire); #if SWIFT_PTRAUTH uint16_t extraDiscriminator = assocType->Flags.getExtraDiscriminator(); @@ -4819,6 +4827,8 @@ swift::swift_getAssociatedTypeWitness(MetadataRequest request, reqBase, assocType); } +using AssociatedConformanceWitness = std::atomic; + SWIFT_CC(swift) static const WitnessTable *swift_getAssociatedConformanceWitnessSlowImpl( WitnessTable *wtable, @@ -4844,8 +4854,8 @@ static const WitnessTable *swift_getAssociatedConformanceWitnessSlowImpl( // Retrieve the witness. unsigned witnessIndex = assocConformance - reqBase; - auto *witnessAddr = &((void**)wtable)[witnessIndex]; - auto witness = *witnessAddr; + auto *witnessAddr = &((AssociatedConformanceWitness*)wtable)[witnessIndex]; + auto witness = witnessAddr->load(std::memory_order_acquire); #if SWIFT_PTRAUTH // For associated protocols, the witness is signed with address @@ -4903,9 +4913,18 @@ static const WitnessTable *swift_getAssociatedConformanceWitnessSlowImpl( // The access function returns an unsigned pointer for now. - // We can't just use initAssociatedConformanceProtocolWitness because we - // also use this function for base protocols. - initProtocolWitness(witnessAddr, assocWitnessTable, *assocConformance); + auto valueToStore = assocWitnessTable; +#if SWIFT_PTRAUTH + if (assocConformance->Flags.isSignedWithAddress()) { + uint16_t extraDiscriminator = + assocConformance->Flags.getExtraDiscriminator(); + valueToStore = ptrauth_sign_unauthenticated(valueToStore, + swift_ptrauth_key_associated_conformance, + ptrauth_blend_discriminator(witnessAddr, + extraDiscriminator)); + } +#endif + witnessAddr->store(valueToStore, std::memory_order_release); return assocWitnessTable; } @@ -4926,8 +4945,8 @@ const WitnessTable *swift::swift_getAssociatedConformanceWitness( // Retrieve the witness. unsigned witnessIndex = assocConformance - reqBase; - auto *witnessAddr = &((const void* *)wtable)[witnessIndex]; - auto witness = *witnessAddr; + auto *witnessAddr = &((AssociatedConformanceWitness*)wtable)[witnessIndex]; + auto witness = witnessAddr->load(std::memory_order_acquire); #if SWIFT_PTRAUTH uint16_t extraDiscriminator = assocConformance->Flags.getExtraDiscriminator(); diff --git a/test/Constraints/closures.swift b/test/Constraints/closures.swift index 2eacf3e1b4497..1b290fb44ca1e 100644 --- a/test/Constraints/closures.swift +++ b/test/Constraints/closures.swift @@ -504,7 +504,7 @@ struct S_3520 { func sr3520_set_via_closure(_ closure: (inout S, T) -> ()) {} // expected-note {{in call to function 'sr3520_set_via_closure'}} sr3520_set_via_closure({ $0.number1 = $1 }) // expected-error@-1 {{generic parameter 'S' could not be inferred}} -// expected-error@-2 {{generic parameter 'T' could not be inferred}} +// expected-error@-2 {{unable to infer type of a closure parameter $1 in the current context}} // SR-3073: UnresolvedDotExpr in single expression closure @@ -1017,3 +1017,21 @@ func overloaded_with_default_and_autoclosure(b: Int = 0, c: @escaping () -> T overloaded_with_default_and_autoclosure { 42 } // Ok overloaded_with_default_and_autoclosure(42) // Ok + +// SR-12815 - `error: type of expression is ambiguous without more context` in many cases where methods are missing +func sr12815() { + let _ = { a, b in } + // expected-error@-1 {{unable to infer type of a closure parameter 'a' in the current context}} + // expected-error@-2 {{unable to infer type of a closure parameter 'b' in the current context}} + + _ = .a { b in } // expected-error {{cannot infer contextual base in reference to member 'a'}} + + struct S {} + + func test(s: S) { + S.doesntExist { b in } // expected-error {{type 'S' has no member 'doesntExist'}} + s.doesntExist { b in } // expected-error {{value of type 'S' has no member 'doesntExist'}} + s.doesntExist1 { v in } // expected-error {{value of type 'S' has no member 'doesntExist1'}} + .doesntExist2() { $0 } + } +} diff --git a/test/Constraints/diagnostics.swift b/test/Constraints/diagnostics.swift index 2e2fb2ab35813..c10f96ad1e126 100644 --- a/test/Constraints/diagnostics.swift +++ b/test/Constraints/diagnostics.swift @@ -255,8 +255,7 @@ struct Toe { let toenail: Nail // expected-error {{cannot find type 'Nail' in scope}} func clip() { - // TODO(diagnostics): Solver should stop once it has detected that `toenail` doesn't exist and report that. - toenail.inspect { x in // expected-error {{type of expression is ambiguous without more context}} + toenail.inspect { x in toenail.inspect { y in } } } @@ -297,7 +296,7 @@ func r18800223(_ i : Int) { } // Bogus "'_' can only appear in a pattern or on the left side of an assignment" is back -_ = { $0 } // expected-error {{unable to infer closure type in the current context}} +_ = { $0 } // expected-error {{unable to infer type of a closure parameter $0 in the current context}} diff --git a/test/Constraints/members.swift b/test/Constraints/members.swift index 54763e96a9c8b..8ed8b54f5b73f 100644 --- a/test/Constraints/members.swift +++ b/test/Constraints/members.swift @@ -615,16 +615,13 @@ func rdar50679161() { func rdar_50467583_and_50909555() { - if #available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) { - // rdar://problem/50467583 - let _: Set = [Int][] // expected-error {{no exact matches in call to subscript}} - // expected-note@-1 {{found candidate with type '(Int) -> Int'}} - // expected-note@-2 {{found candidate with type '(Range) -> ArraySlice'}} - // expected-note@-3 {{found candidate with type '((UnboundedRange_) -> ()) -> ArraySlice'}} - // expected-note@-4 {{found candidate with type '(RangeSet.Index>) -> DiscontiguousSlice<[Int]>' (aka '(RangeSet) -> DiscontiguousSlice>')}} - // expected-note@-5 {{found candidate with type '(Range.Index>) -> Slice<[Int]>' (aka '(Range) -> Slice>')}} - } - + // rdar://problem/50467583 + let _: Set = [Int][] // expected-error {{no exact matches in call to subscript}} + // expected-note@-1 {{found candidate with type '(Int) -> Int'}} + // expected-note@-2 {{found candidate with type '(Range) -> ArraySlice'}} + // expected-note@-3 {{found candidate with type '((UnboundedRange_) -> ()) -> ArraySlice'}} + // expected-note@-4 {{found candidate with type '(Range.Index>) -> Slice<[Int]>' (aka '(Range) -> Slice>')}} + // rdar://problem/50909555 struct S { static subscript(x: Int, y: Int) -> Int { // expected-note {{'subscript(_:_:)' declared here}} diff --git a/test/IDE/complete_call_arg.swift b/test/IDE/complete_call_arg.swift index ba59d28f333d1..4e297bf18e338 100644 --- a/test/IDE/complete_call_arg.swift +++ b/test/IDE/complete_call_arg.swift @@ -104,6 +104,8 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TUPLEELEM_1 | %FileCheck %s -check-prefix=TUPLEELEM_1 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TUPLEELEM_2 | %FileCheck %s -check-prefix=TUPLEELEM_2 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=KEYPATH_THUNK_BASE | %FileCheck %s -check-prefix=KEYPATH_THUNK_BASE + var i1 = 1 var i2 = 2 var oi1 : Int? @@ -829,3 +831,20 @@ func testTupleElement(arg: (SimpleEnum, SimpleEnum)) { testTupleElement(arg: (.foo, .bar, .#^TUPLEELEM_2^#)) // TUPLEELEM_2-NOT: Begin completions } + +func testKeyPathThunkInBase() { + struct TestKP { + var value: Int { 1 } + } + struct TestKPResult { + func testFunc(_ arg: SimpleEnum) {} + } + func foo(_ fn: (TestKP) -> Int) -> TestKPResult { TestKPResult() } + + foo(\.value).testFunc(.#^KEYPATH_THUNK_BASE^#) +// KEYPATH_THUNK_BASE: Begin completions, 3 items +// KEYPATH_THUNK_BASE-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: foo[#SimpleEnum#]; name=foo +// KEYPATH_THUNK_BASE-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: bar[#SimpleEnum#]; name=bar +// KEYPATH_THUNK_BASE-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: baz[#SimpleEnum#]; name=baz +// KEYPATH_THUNK_BASE: End completions +} diff --git a/test/IDE/complete_opaque_result.swift b/test/IDE/complete_opaque_result.swift index ef7accb15c7b2..03a95395d1276 100644 --- a/test/IDE/complete_opaque_result.swift +++ b/test/IDE/complete_opaque_result.swift @@ -22,6 +22,9 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=POSTFIX_TestProtocol_DOT | %FileCheck %s -check-prefix=POSTFIX_TestProtocol_DOT // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=POSTFIX_TestProtocol_NODOT | %FileCheck %s -check-prefix=POSTFIX_TestProtocol_NODOT +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OVERRIDE_TestProtocol2 | %FileCheck %s -check-prefix=OVERRIDE_TestProtocol2 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=POSTFIX_ConcreteTestProtocol2 | %FileCheck %s -check-prefix=POSTFIX_ConcreteTestProtocol2 + protocol MyProtocol { associatedtype Mistery } @@ -200,3 +203,36 @@ func postfixExpr() { // POSTFIX_TestProtocol_NODOT-DAG: BuiltinOperator/None: = {#TestProtocol#}[#Void#]; name={{.*$}} // POSTFIX_TestProtocol_NODOT-DAG: Keyword[self]/CurrNominal: .self[#TestProtocol#]; name={{.*$}} // POSTFIX_TestProtocol_NODOT-DAG: End completions + +protocol TestProtocol2 { + associatedtype Assoc: Comparable + func foo() -> Assoc + func bar() -> Assoc + func baz(x: @autoclosure () -> Assoc) -> (Assoc) -> Assoc +} +extension TestProtocol2 { + func inExt() -> Assoc { fatalError() } +} +struct ConcreteTestProtocol2: TestProtocol2 { + func foo() -> some Comparable { 1 } + #^OVERRIDE_TestProtocol2^# +// OVERRIDE_TestProtocol2: Begin completions +// OVERRIDE_TestProtocol2-NOT: foo() +// OVERRIDE_TestProtocol2-NOT: inExt() +// OVERRIDE_TestProtocol2-DAG: Decl[InstanceMethod]/Super: func bar() -> Assoc {|}; +// OVERRIDE_TestProtocol2-DAG: Decl[InstanceMethod]/Super: func baz(x: @autoclosure () -> Assoc) -> (Assoc) -> Assoc {|}; +// OVERRIDE_TestProtocol2-DAG: Decl[AssociatedType]/Super: typealias Assoc = {#(Type)#}; +// OVERRIDE_TestProtocol2-NOT: foo() +// OVERRIDE_TestProtocol2-NOT: inExt() +// OVERRIDE_TestProtocol2: End completions +} +func testUseTestProtocol2(value: ConcreteTestProtocol2) { + value.#^POSTFIX_ConcreteTestProtocol2^# +// POSTFIX_ConcreteTestProtocol2: Begin completions +// POSTFIX_ConcreteTestProtocol2-DAG: Keyword[self]/CurrNominal: self[#ConcreteTestProtocol2#]; +// POSTFIX_ConcreteTestProtocol2-DAG: Decl[InstanceMethod]/CurrNominal: foo()[#Comparable#]; +// POSTFIX_ConcreteTestProtocol2-DAG: Decl[InstanceMethod]/Super: bar()[#ConcreteTestProtocol2.Assoc#]; +// POSTFIX_ConcreteTestProtocol2-DAG: Decl[InstanceMethod]/Super: baz({#x: ConcreteTestProtocol2.Assoc#})[#(ConcreteTestProtocol2.Assoc) -> ConcreteTestProtocol2.Assoc#]; +// POSTFIX_ConcreteTestProtocol2-DAG: Decl[InstanceMethod]/Super: inExt()[#ConcreteTestProtocol2.Assoc#]; +// POSTFIX_ConcreteTestProtocol2: End completions +} diff --git a/test/Runtime/associated_witness_concurrency.swift b/test/Runtime/associated_witness_concurrency.swift new file mode 100644 index 0000000000000..8dda259621249 --- /dev/null +++ b/test/Runtime/associated_witness_concurrency.swift @@ -0,0 +1,48 @@ +// RUN: %target-swiftc_driver %s -g %import-libdispatch -o %t +// RUN: %target-codesign %t +// RUN: %target-run %t +// REQUIRES: libdispatch +// REQUIRES: executable_test + +import Dispatch + +protocol P { + associatedtype Unused +} +struct A : P { + // We never actually read this associated type, but its presence in the + // wtable should force it to be instantiated rather than shared for + // all specializations of A. + typealias Unused = A> +} + +protocol Q { + associatedtype Assoc: P + + func foo() +} +struct B : Q { + // Both the metadata and the wtable for this associated type require + // runtime instantiation and must be fetched lazily. + typealias Assoc = A + + func foo() {} +} + +// It's possible that the optimizer might someday be able to recognize +// that this is a no-op. +func rundown(value: T, count: Int) { + guard count > 0 else { return } + + value.foo() + + // Assuming that T is B for some U, this constructs B>, + // which will be T in the recursive call; i.e. we should have a + // different metadata/wtable pair each time. In order to construct + // that, we have to read the associated metadata and wtable for T.Assoc. + rundown(value: B(), count: count - 1) +} + +DispatchQueue.concurrentPerform(iterations: 5) { n in + rundown(value: B>(), count: 1000) +} diff --git a/test/SILGen/Inputs/objc_init_unavailable.h b/test/SILGen/Inputs/objc_init_unavailable.h new file mode 100644 index 0000000000000..b99fc40093c3f --- /dev/null +++ b/test/SILGen/Inputs/objc_init_unavailable.h @@ -0,0 +1,6 @@ +@import Foundation; + +@interface ClassWithUnavailableInit : NSObject + +- (instancetype)initWithBundleID:(NSString *)bundleID __attribute__((availability(macos, unavailable))); +@end diff --git a/test/SILGen/memberwise_init_temporary_allocations.swift b/test/SILGen/memberwise_init_temporary_allocations.swift new file mode 100644 index 0000000000000..cae60e17be803 --- /dev/null +++ b/test/SILGen/memberwise_init_temporary_allocations.swift @@ -0,0 +1,18 @@ +// RUN: %target-swift-emit-silgen -verify %s + +protocol P { var x: Int { get } } + +extension Int: P { var x: Int { return self } } + +// rdar://problem/63187509: Evaluating the variable initializer for `px` +// requires allocating a temporary stack slot for the address only value of +// `Butt.p`. Ensure that this gets cleaned up appropriately (which is asserted +// by the SIL verifier). +struct Butt { + static var p: P = 0 + + let px = Butt.p.x + + let y: Int +} + diff --git a/test/SILGen/objc_init_unavailable.swift b/test/SILGen/objc_init_unavailable.swift new file mode 100644 index 0000000000000..3cc885ff775fc --- /dev/null +++ b/test/SILGen/objc_init_unavailable.swift @@ -0,0 +1,19 @@ +// RUN: %target-swift-emit-silgen(mock-sdk: %clang-importer-sdk) -enable-objc-interop -import-objc-header %S/Inputs/objc_init_unavailable.h %s | %FileCheck %s +// REQUIRES: objc_interop + +@available(macOS, unavailable) +public func callUnavailableInit(name: String) -> ClassWithUnavailableInit { + return ClassWithUnavailableInit(bundleID: name) +} + +// CHECK-LABEL: sil [ossa] @$s21objc_init_unavailable19callUnavailableInit4nameSo09ClassWitheF0CSS_tF : $@convention(thin) (@guaranteed String) -> @owned ClassWithUnavailableInit { +// CHECK: function_ref @$sSo24ClassWithUnavailableInitC8bundleIDABSgSSSg_tcfC : $@convention(method) (@owned Optional, @thick ClassWithUnavailableInit.Type) -> @owned Optional +// CHECK: return + +// CHECK-LABEL: sil shared [serializable] [ossa] @$sSo24ClassWithUnavailableInitC8bundleIDABSgSSSg_tcfC : $@convention(method) (@owned Optional, @thick ClassWithUnavailableInit.Type) -> @owned Optional { +// CHECK: function_ref @$sSo24ClassWithUnavailableInitC8bundleIDABSgSSSg_tcfcTO : $@convention(method) (@owned Optional, @owned ClassWithUnavailableInit) -> @owned Optional +// CHECK: return + +// CHECK-LABEL: sil shared [serializable] [thunk] [ossa] @$sSo24ClassWithUnavailableInitC8bundleIDABSgSSSg_tcfcTO : $@convention(method) (@owned Optional, @owned ClassWithUnavailableInit) -> @owned Optional { +// CHECK: objc_method %1 : $ClassWithUnavailableInit, #ClassWithUnavailableInit.init!initializer.foreign : (ClassWithUnavailableInit.Type) -> (String?) -> ClassWithUnavailableInit?, $@convention(objc_method) (Optional, @owned ClassWithUnavailableInit) -> @owned Optional +// CHECK: return \ No newline at end of file diff --git a/test/SILGen/opaque_type_lowering_in_substitution.swift b/test/SILGen/opaque_type_lowering_in_substitution.swift new file mode 100644 index 0000000000000..903de21148a03 --- /dev/null +++ b/test/SILGen/opaque_type_lowering_in_substitution.swift @@ -0,0 +1,16 @@ +// RUN: %target-swift-emit-silgen -disable-availability-checking -verify %s +protocol P {} +extension Int: P {} + +func foo() -> some P { return 0 } +func bar(_ x: T) -> some P { return x } + +struct Bas { init(_: T) {} } + +func abstraction_level(x: T) -> (T) -> () { + return { _ in () } +} + +func test() { + abstraction_level(x: Bas(bar(foo())))(Bas(bar(foo()))) +} diff --git a/test/Sema/diag_ambiguous_overloads.swift b/test/Sema/diag_ambiguous_overloads.swift index 339ff22671bfa..10712fc3531c3 100644 --- a/test/Sema/diag_ambiguous_overloads.swift +++ b/test/Sema/diag_ambiguous_overloads.swift @@ -15,15 +15,15 @@ fe(.baz) // expected-error {{reference to member 'baz' cannot be resolved withou fe(.nope, .nyet) // expected-error {{type 'Int' has no member 'nope'}} // expected-error@-1 {{reference to member 'nyet' cannot be resolved without a contextual type}} -func fg(_ f: (T) -> T) -> Void {} // expected-note {{in call to function 'fg'}} -fg({x in x}) // expected-error {{generic parameter 'T' could not be inferred}} +func fg(_ f: (T) -> T) -> Void {} +fg({x in x}) // expected-error {{unable to infer type of a closure parameter 'x' in the current context}} struct S { - func f(_ i: (T) -> T, _ j: Int) -> Void {} // expected-note {{in call to function 'f'}} + func f(_ i: (T) -> T, _ j: Int) -> Void {} func f(_ d: (Double) -> Double) -> Void {} func test() -> Void { - f({x in x}, 2) // expected-error {{generic parameter 'T' could not be inferred}} + f({x in x}, 2) // expected-error {{unable to infer type of a closure parameter 'x' in the current context}} } func g(_ a: T, _ b: Int) -> Void {} diff --git a/test/Sema/keypath_subscript_nolabel.swift b/test/Sema/keypath_subscript_nolabel.swift new file mode 100644 index 0000000000000..ef1a135538b3b --- /dev/null +++ b/test/Sema/keypath_subscript_nolabel.swift @@ -0,0 +1,35 @@ +// RUN: %target-swift-frontend -typecheck -verify -primary-file %s +// [SR-12745] +// rdar://problem/62957095 +struct S1 { + var x : Int = 0 +} +var s1 = S1() +s1[\.x] = 10 // expected-error {{missing argument label 'keyPath:' in subscript}} {{4-4=keyPath: }} + +struct S2 { + var x : Int = 0 + subscript(_ v: Int) -> Int { 0 } +} +var s2 = S2() +s2[\.x] = 10 // expected-error {{missing argument label 'keyPath:' in subscript}} {{4-4=keyPath: }} + +struct S3 { + var x : Int = 0 + subscript(v v: KeyPath) -> Int { get { 0 } set(newValue) {} } +} +var s3 = S3() +// TODO(diagnostics): This should actually be a diagnostic that correctly identifies that in the presence +// of a missing label, there are two options for resolution: 'keyPath' and 'v:' and to offer the user +// a choice. +// Today, the ExprTypeChecker identifies the disjunction with two of these possibilities, but +// filters out some of the terms based on label mismatch (but not implicit keypath terms, for example). +// It should probably not do that. +s3[\.x] = 10 // expected-error {{missing argument label 'keyPath:' in subscript}} {{4-4=keyPath: }} + +struct S4 { + var x : Int = 0 + subscript(v: KeyPath) -> Int { get { 0 } set(newValue) {} } +} +var s4 = S4() +s4[\.x] = 10 // expected-error {{key path value type 'Int' cannot be converted to contextual type 'String'}} diff --git a/test/SourceKit/CursorInfo/cursor_opaque_result.swift b/test/SourceKit/CursorInfo/cursor_opaque_result.swift new file mode 100644 index 0000000000000..33030a3bc3c58 --- /dev/null +++ b/test/SourceKit/CursorInfo/cursor_opaque_result.swift @@ -0,0 +1,35 @@ +public protocol P { + associatedtype Assoc + func foo() -> Assoc +} +extension P { + func bar() -> Assoc { fatalError() } +} + +public struct MyStruct: P { + public func foo() -> some Comparable { 1 } +} +func test(value: MyStruct) { + value.foo() + value.bar() +} + +// RUN: %sourcekitd-test -req=cursor -pos=13:9 %s -- %s -module-name MyModule | %FileCheck --check-prefix=OPAQUE %s +// RUN: %sourcekitd-test -req=cursor -pos=14:9 %s -- %s -module-name MyModule | %FileCheck --check-prefix=ASSOC %s + +// OPAQUE: foo() +// OPAQUE-NEXT: s:8MyModule0A6StructV3fooQryF +// OPAQUE-NEXT: (MyStruct) -> () -> some Comparable +// OPAQUE-NEXT: $sQrycD +// OPAQUE-NEXT: $s8MyModule0A6StructVD +// OPAQUE-NEXT: public func foo() -> some Comparable +// OPAQUE-NEXT: public func foo() -> some Comparable + + +// ASSOC: bar() +// ASSOC-NEXT: s:8MyModule1PPAAE3bar5AssocQzyF +// ASSOC-NEXT: (Self) -> () -> Self.Assoc +// ASSOC-NEXT: $s5AssocQzycD +// ASSOC-NEXT: $s8MyModule0A6StructVD +// ASSOC-NEXT: func bar() -> Assoc +// ASSOC-NEXT: func bar() -> Assoc diff --git a/test/decl/typealias/generic.swift b/test/decl/typealias/generic.swift index 561d9cdb6b193..805226a7f28b6 100644 --- a/test/decl/typealias/generic.swift +++ b/test/decl/typealias/generic.swift @@ -68,7 +68,7 @@ typealias E = Int // expected-note {{generic type 'E' declared here}} // expected-note@-1 {{'T1' declared as parameter to type 'E'}} // expected-note@-2 {{'T2' declared as parameter to type 'E'}} -typealias F = (T1) -> T2 // expected-note {{'T1' declared as parameter to type 'F'}} +typealias F = (T1) -> T2 // Type alias of type alias. typealias G = A @@ -94,7 +94,7 @@ let _ : D = D(a: 1, b: 2) let _ : F = { (a : Int) -> Int in a } // Infer the types of F -let _ : F = { a in a } // expected-error {{generic parameter 'T1' could not be inferred}} +let _ : F = { a in a } // expected-error {{unable to infer type of a closure parameter 'a' in the current context}} _ = MyType(a: "foo", b: 42) _ = A(a: "foo", b: 42) diff --git a/test/expr/closure/anonymous.swift b/test/expr/closure/anonymous.swift index f48c6e62ce4df..566fa0cc1bcc8 100644 --- a/test/expr/closure/anonymous.swift +++ b/test/expr/closure/anonymous.swift @@ -13,7 +13,7 @@ func takesIntArray(_: [Int]) { } func takesVariadicInt(_: (Int...) -> ()) { } func takesVariadicIntInt(_: (Int, Int...) -> ()) { } -func takesVariadicGeneric(_ f: (T...) -> ()) { } // expected-note {{in call to function 'takesVariadicGeneric'}} +func takesVariadicGeneric(_ f: (T...) -> ()) { } func variadic() { // These work @@ -32,7 +32,7 @@ func variadic() { // FIXME: Problem here is related to multi-statement closure body not being type-checked together with // enclosing context. We could have inferred `$0` to be `[Int]` if `let` was a part of constraint system. takesVariadicGeneric({let _: [Int] = $0}) - // expected-error@-1 {{generic parameter 'T' could not be inferred}} + // expected-error@-1 {{unable to infer type of a closure parameter $0 in the current context}} takesVariadicIntInt({_ = $0; takesIntArray($1)}) takesVariadicIntInt({_ = $0; let _: [Int] = $1}) diff --git a/test/expr/closure/basic.swift b/test/expr/closure/basic.swift index 82c7d91926b2c..16a9c794e79dc 100644 --- a/test/expr/closure/basic.swift +++ b/test/expr/closure/basic.swift @@ -26,7 +26,7 @@ func variadic() { _ = f(1, 2) _ = f(1, 3) - let D = { (Ss ...) in 1 } // expected-error{{'...' cannot be applied to a subpattern which is not explicitly typed}}, expected-error{{unable to infer closure type in the current context}} + let D = { (Ss ...) in 1 } // expected-error{{'...' cannot be applied to a subpattern which is not explicitly typed}}, expected-error{{unable to infer type of a closure parameter 'Ss' in the current context}} } // Closures with attributes in the parameter list. diff --git a/test/expr/unary/keypath/salvage-with-other-type-errors.swift b/test/expr/unary/keypath/salvage-with-other-type-errors.swift index e06c026159eff..56aeeb10982e9 100644 --- a/test/expr/unary/keypath/salvage-with-other-type-errors.swift +++ b/test/expr/unary/keypath/salvage-with-other-type-errors.swift @@ -34,7 +34,7 @@ extension A: K { struct B { let v: String - func f1(block: (T) -> E) -> B { // expected-note {{in call to function 'f1(block:)'}} + func f1(block: (T) -> E) -> B { return self } @@ -42,7 +42,7 @@ struct B { } } func f3() { - B(v: "").f1(block: { _ in }).f2(keyPath: \B.v) // expected-error{{}} + B(v: "").f1(block: { _ in }).f2(keyPath: \B.v) // expected-error{{unable to infer type of a closure parameter '_' in the current context}} } // SR-5375 diff --git a/test/type/types.swift b/test/type/types.swift index 7716a1582c3cf..e1a1115e7d363 100644 --- a/test/type/types.swift +++ b/test/type/types.swift @@ -18,17 +18,13 @@ var d3 : () -> Float = { 4 } var d4 : () -> Int = { d2 } // expected-error{{function produces expected type 'Int'; did you mean to call it with '()'?}} {{26-26=()}} -if #available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) { - var e0 : [Int] - e0[] // expected-error {{no exact matches in call to subscript}} - // expected-note@-1 {{candidate has partially matching parameter list (Int)}} - // expected-note@-2 {{candidate has partially matching parameter list (Range)}} - // expected-note@-3 {{candidate has partially matching parameter list ((UnboundedRange_) -> ())}} - // expected-note@-4 {{candidate has partially matching parameter list (RangeSet.Index>)}} - // expected-note@-5 {{candidate has partially matching parameter list (Range.Index>)}} - // expected-note@-6 {{candidate has partially matching parameter list ((UnboundedRange_) -> ())}} - // expected-note@-7 {{candidate has partially matching parameter list (RangeSet.Index>)}} -} +var e0 : [Int] +e0[] // expected-error {{no exact matches in call to subscript}} +// expected-note@-1 {{candidate has partially matching parameter list (Int)}} +// expected-note@-2 {{candidate has partially matching parameter list (Range)}} +// expected-note@-3 {{candidate has partially matching parameter list ((UnboundedRange_) -> ())}} +// expected-note@-4 {{candidate has partially matching parameter list (Range.Index>)}} +// expected-note@-5 {{candidate has partially matching parameter list ((UnboundedRange_) -> ())}} var f0 : [Float] var f1 : [(Int,Int)] diff --git a/validation-test/StdlibUnittest/RangeSet.swift b/validation-test/StdlibUnittest/RangeSet.swift deleted file mode 100644 index 61bd605f80e4b..0000000000000 --- a/validation-test/StdlibUnittest/RangeSet.swift +++ /dev/null @@ -1,363 +0,0 @@ -// RUN: %target-run-simple-swift -// REQUIRES: executable_test - -import StdlibUnittest -import StdlibCollectionUnittest - -@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) -extension RangeSet: ExpressibleByArrayLiteral { - public init(arrayLiteral elements: Range...) { - self.init(elements) - } -} - -extension Collection { - func every(_ n: Int) -> [Element] { - sequence(first: startIndex) { i in - self.index(i, offsetBy: n, limitedBy: self.endIndex) - }.map { self[$0] } - } -} - -let RangeSetTests = TestSuite("RangeSet") - -if #available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) { - - let parent = -200..<200 - let source: RangeSet = [1..<5, 8..<10, 20..<22, 27..<29] - - let letterString = "ABCdefGHIjklMNOpqrStUvWxyz" - let lowercaseLetters = letterString.filter { $0.isLowercase } - let uppercaseLetters = letterString.filter { $0.isUppercase } - - func buildRandomRangeSet(iterations: Int = 100) -> RangeSet { - var set = RangeSet() - for _ in 0..<100 { - var (a, b) = (Int.random(in: -100...100), Int.random(in: -100...100)) - if (a > b) { swap(&a, &b) } - if Double.random(in: 0..<1) > 0.3 { - set.insert(contentsOf: a.., _ s2: RangeSet) -> RangeSet { - let set1 = Set(parent.indices[s1]) - let set2 = Set(parent.indices[s2]) - return RangeSet(set1.intersection(set2), within: parent) - } - - do { - // Simple test - let set1: RangeSet = [0..<5, 9..<14] - let set2: RangeSet = [1..<3, 4..<6, 8..<12] - let intersection: RangeSet = [1..<3, 4..<5, 9..<12] - expectEqual(set1.intersection(set2), intersection) - expectEqual(set2.intersection(set1), intersection) - } - - do { - // Test with upper bound / lower bound equality - let set1: RangeSet = [10..<20, 30..<40] - let set2: RangeSet = [15..<30, 40..<50] - let intersection: RangeSet = [15..<20] - expectEqual(set1.intersection(set2), intersection) - expectEqual(set2.intersection(set1), intersection) - } - - for _ in 0..<100 { - let set1 = buildRandomRangeSet() - let set2 = buildRandomRangeSet() - - let rangeSetIntersection = set1.intersection(set2) - let stdlibSetIntersection = intersectionViaSet(set1, set2) - expectEqual(rangeSetIntersection, stdlibSetIntersection) - } - } - - RangeSetTests.test("symmetricDifference") { - func symmetricDifferenceViaSet(_ s1: RangeSet, _ s2: RangeSet) -> RangeSet { - let set1 = Set(parent.indices[s1]) - let set2 = Set(parent.indices[s2]) - return RangeSet(set1.symmetricDifference(set2), within: parent) - } - - do { - // Simple test - let set1: RangeSet = [0..<5, 9..<14] - let set2: RangeSet = [1..<3, 4..<6, 8..<12] - let difference: RangeSet = [0..<1, 3..<4, 5..<6, 8..<9, 12..<14] - expectEqual(set1.symmetricDifference(set2), difference) - expectEqual(set2.symmetricDifference(set1), difference) - } - - do { - // Test with upper bound / lower bound equality - let set1: RangeSet = [10..<20, 30..<40] - let set2: RangeSet = [15..<30, 40..<50] - let difference: RangeSet = [10..<15, 20..<50] - expectEqual(set1.symmetricDifference(set2), difference) - expectEqual(set2.symmetricDifference(set1), difference) - } - - for _ in 0..<100 { - let set1 = buildRandomRangeSet() - let set2 = buildRandomRangeSet() - - let rangeSetDifference = set1.symmetricDifference(set2) - let stdlibSetDifference = symmetricDifferenceViaSet(set1, set2) - expectEqual(rangeSetDifference, stdlibSetDifference) - } - } - - RangeSetTests.test("subranges(of:/where:)") { - let a = [1, 2, 3, 4, 3, 3, 4, 5, 3, 4, 3, 3, 3] - let indices = a.subranges(of: 3) - expectEqual(indices, [2..<3, 4..<6, 8..<9, 10..<13]) - - let allTheThrees = a[indices] - expectEqual(allTheThrees.count, 7) - expectTrue(allTheThrees.allSatisfy { $0 == 3 }) - expectEqual(Array(allTheThrees), Array(repeating: 3, count: 7)) - - let lowerIndices = letterString.subranges(where: { $0.isLowercase }) - let lowerOnly = letterString[lowerIndices] - expectEqualSequence(lowerOnly, lowercaseLetters) - expectEqualSequence(lowerOnly.reversed(), lowercaseLetters.reversed()) - - let upperOnly = letterString.removingSubranges(lowerIndices) - expectEqualSequence(upperOnly, uppercaseLetters) - expectEqualSequence(upperOnly.reversed(), uppercaseLetters.reversed()) - } - - RangeSetTests.test("removeSubranges") { - var a = [1, 2, 3, 4, 3, 3, 4, 5, 3, 4, 3, 3, 3] - let indices = a.subranges(of: 3) - a.removeSubranges(indices) - expectEqual(a, [1, 2, 4, 4, 5, 4]) - - var numbers = Array(1...20) - numbers.removeSubranges(RangeSet([2..<5, 10..<15, 18..<20])) - expectEqual(numbers, [1, 2, 6, 7, 8, 9, 10, 16, 17, 18]) - - numbers = Array(1...20) - numbers.removeSubranges([]) - expectEqual(numbers, Array(1...20)) - - let sameNumbers = numbers.removingSubranges([]) - expectEqualSequence(numbers, sameNumbers) - - let noNumbers = numbers.removingSubranges(RangeSet(numbers.indices)) - expectEqualSequence(EmptyCollection(), noNumbers) - - var str = letterString - let lowerIndices = str.subranges(where: { $0.isLowercase }) - - let upperOnly = str.removingSubranges(lowerIndices) - expectEqualSequence(upperOnly, uppercaseLetters) - - str.removeSubranges(lowerIndices) - expectEqualSequence(str, uppercaseLetters) - } - - RangeSetTests.test("moveSubranges/rangeset") { - // Move before - var numbers = Array(1...20) - let range1 = numbers.moveSubranges(RangeSet([10..<15, 18..<20]), to: 4) - expectEqual(range1, 4..<11) - expectEqual(numbers, [ - 1, 2, 3, 4, - 11, 12, 13, 14, 15, - 19, 20, - 5, 6, 7, 8, 9, 10, 16, 17, 18]) - - // Move to start - numbers = Array(1...20) - let range2 = numbers.moveSubranges(RangeSet([10..<15, 18..<20]), to: 0) - expectEqual(range2, 0..<7) - expectEqual(numbers, [ - 11, 12, 13, 14, 15, - 19, 20, - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 16, 17, 18]) - - // Move to end - numbers = Array(1...20) - let range3 = numbers.moveSubranges(RangeSet([10..<15, 18..<20]), to: 20) - expectEqual(range3, 13..<20) - expectEqual(numbers, [ - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 16, 17, 18, - 11, 12, 13, 14, 15, - 19, 20, - ]) - - // Move to middle of selected elements - numbers = Array(1...20) - let range4 = numbers.moveSubranges(RangeSet([10..<15, 18..<20]), to: 14) - expectEqual(range4, 10..<17) - expectEqual(numbers, [ - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, - 19, 20, - 16, 17, 18]) - - // Move none - numbers = Array(1...20) - let range5 = numbers.moveSubranges(RangeSet(), to: 10) - expectEqual(range5, 10..<10) - expectEqual(numbers, Array(1...20)) - } - - RangeSetTests.test("moveSubranges/noCOW") { - let numbers = Array(1...20) - expectNoCopyOnWrite(numbers) { numbers in - numbers.moveSubranges(RangeSet([10..<15, 18..<20]), to: 4) - } - expectNoCopyOnWrite(numbers) { numbers in - numbers.removeSubranges(RangeSet([2..<5, 10..<15, 18..<20])) - } - } - - RangeSetTests.test("DiscontiguousSliceSlicing") { - let initial = 1...100 - - // Build an array of ranges that include alternating groups of 5 elements - // e.g. 1...5, 11...15, etc - let rangeStarts = initial.indices.every(10) - let rangeEnds = rangeStarts.compactMap { - initial.index($0, offsetBy: 5, limitedBy: initial.endIndex) - } - let ranges = zip(rangeStarts, rangeEnds).map(Range.init) - - // Create a collection of the elements represented by `ranges` without - // using `RangeSet` - let chosenElements = ranges.map { initial[$0] }.joined() - - let set = RangeSet(ranges) - let discontiguousSlice = initial[set] - expectEqualSequence(discontiguousSlice, chosenElements) - - for (chosenIdx, disIdx) in zip(chosenElements.indices, discontiguousSlice.indices) { - expectEqualSequence(chosenElements[chosenIdx...], discontiguousSlice[disIdx...]) - expectEqualSequence(chosenElements[.. Bool { return arr.compactMap { i in - // expected-error@-1 {{generic parameter 'ElementOfResult' could not be inferred}} var flag = false return try? i.getB(&flag) - }.compactMap { u -> P? in + }.compactMap { u -> P? in // expected-error {{nable to infer type of a closure parameter 'u' in the current context}} guard let a = try? u.foo() else { return nil } return a.value! }.contains {