diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index dcac2cb90e979..458bce26c6011 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -514,7 +514,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated { IsComputingSemanticMembers : 1 ); - SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+1+1+8+16, + SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+1+1+1+1+8+16, /// Whether the \c RequiresClass bit is valid. RequiresClassValid : 1, @@ -527,6 +527,12 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated { /// Whether the existential of this protocol conforms to itself. ExistentialConformsToSelf : 1, + /// Whether the \c ExistentialTypeSupported bit is valid. + ExistentialTypeSupportedValid : 1, + + /// Whether the existential of this protocol can be represented. + ExistentialTypeSupported : 1, + /// True if the protocol has requirements that cannot be satisfied (e.g. /// because they could not be imported from Objective-C). HasMissingRequirements : 1, @@ -4145,6 +4151,21 @@ class ProtocolDecl final : public NominalTypeDecl { Bits.ProtocolDecl.ExistentialConformsToSelf = result; } + /// Returns the cached result of \c existentialTypeSupported or \c None if it + /// hasn't yet been computed. + Optional getCachedExistentialTypeSupported() { + if (Bits.ProtocolDecl.ExistentialTypeSupportedValid) + return Bits.ProtocolDecl.ExistentialTypeSupported; + + return None; + } + + /// Caches the result of \c existentialTypeSupported + void setCachedExistentialTypeSupported(bool supported) { + Bits.ProtocolDecl.ExistentialTypeSupportedValid = true; + Bits.ProtocolDecl.ExistentialTypeSupported = supported; + } + bool hasLazyRequirementSignature() const { return Bits.ProtocolDecl.HasLazyRequirementSignature; } @@ -4154,6 +4175,7 @@ class ProtocolDecl final : public NominalTypeDecl { friend class RequirementSignatureRequest; friend class ProtocolRequiresClassRequest; friend class ExistentialConformsToSelfRequest; + friend class ExistentialTypeSupportedRequest; friend class InheritedProtocolsRequest; public: @@ -4242,6 +4264,12 @@ class ProtocolDecl final : public NominalTypeDecl { /// contain 'Self' in 'parameter' or 'other' position. bool isAvailableInExistential(const ValueDecl *decl) const; + /// Determine whether we are allowed to refer to an existential type + /// conforming to this protocol. This is only permitted if the types of + /// all the members do not contain any associated types, and do not + /// contain 'Self' in 'parameter' or 'other' position. + bool existentialTypeSupported() const; + /// Returns a list of protocol requirements that must be assessed to /// determine a concrete's conformance effect polymorphism kind. PolymorphicEffectRequirementList getPolymorphicEffectRequirements( diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 3c7c764f0eff8..b1aa9b8d00fa7 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -920,6 +920,9 @@ NOTE(object_literal_resolve_import,none, ERROR(use_local_before_declaration,none, "use of local variable %0 before its declaration", (DeclNameRef)) +ERROR(unsupported_existential_type,none, + "protocol %0 can only be used as a generic constraint because it has " + "Self or associated type requirements", (Identifier)) ERROR(decl_does_not_exist_in_module,none, "%select{%error|type|struct|class|enum|protocol|variable|function}0 " diff --git a/include/swift/AST/EducationalNotes.def b/include/swift/AST/EducationalNotes.def index bc57ec20410c0..0ba9c1e9fdd13 100644 --- a/include/swift/AST/EducationalNotes.def +++ b/include/swift/AST/EducationalNotes.def @@ -21,8 +21,8 @@ // EDUCATIONAL_NOTES(DIAG_ID, EDUCATIONAL_NOTE_FILENAMES...) -EDUCATIONAL_NOTES(could_not_use_member_on_existential, - "existential-member-access-limitations.md") +EDUCATIONAL_NOTES(unsupported_existential_type, + "associated-type-requirements.md") EDUCATIONAL_NOTES(cannot_pass_type_to_non_ephemeral, "temporary-pointers.md") EDUCATIONAL_NOTES(cannot_pass_type_to_non_ephemeral_warning, diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 7c28cd38b2290..d5ba12351e716 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -287,6 +287,32 @@ class ExistentialConformsToSelfRequest : void cacheResult(bool value) const; }; +/// Determine whether we are allowed to refer to an existential type conforming +/// to this protocol. +class ExistentialTypeSupportedRequest : + public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + // Evaluation. + bool evaluate(Evaluator &evaluator, ProtocolDecl *decl) const; + +public: + // Cycle handling. + void diagnoseCycle(DiagnosticEngine &diags) const; + void noteCycleStep(DiagnosticEngine &diags) const; + + // Separate caching. + bool isCached() const { return true; } + Optional getCachedResult() const; + void cacheResult(bool value) const; +}; + class PolymorphicEffectRequirementsRequest : public SimpleRequestgetSelfType(), position); } - if (auto *const nominal = type->getAs()) { + // Most bound generic types are invariant. + if (auto *const bgt = type->getAs()) { auto info = SelfReferenceInfo(); - // Don't forget to look in the parent. - if (const auto parent = nominal->getParent()) { - info |= findProtocolSelfReferences(proto, parent, position); - } - - // Most bound generic types are invariant. - if (auto *const bgt = type->getAs()) { - if (bgt->isArray()) { - // Swift.Array preserves variance in its Value type. - info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().front(), - position); - } else if (bgt->isDictionary()) { - // Swift.Dictionary preserves variance in its Element type. - info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().front(), + if (bgt->isArray()) { + // Swift.Array preserves variance in its Value type. + info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().front(), + position); + } else if (bgt->isDictionary()) { + // Swift.Dictionary preserves variance in its Element type. + info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().front(), + SelfReferencePosition::Invariant); + info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().back(), + position); + } else { + for (auto paramType : bgt->getGenericArgs()) { + info |= findProtocolSelfReferences(proto, paramType, SelfReferencePosition::Invariant); - info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().back(), - position); - } else { - for (auto paramType : bgt->getGenericArgs()) { - info |= findProtocolSelfReferences(proto, paramType, - SelfReferencePosition::Invariant); - } } } @@ -5044,16 +5037,6 @@ findProtocolSelfReferences(const ProtocolDecl *proto, Type type, if (type->is()) return SelfReferenceInfo::forSelfRef(SelfReferencePosition::Invariant); - // Protocol compositions preserve variance. - if (auto *comp = type->getAs()) { - // 'Self' may be referenced only in a superclass component. - if (const auto superclass = comp->getSuperclass()) { - return findProtocolSelfReferences(proto, superclass, position); - } - - return SelfReferenceInfo(); - } - // A direct reference to 'Self'. if (proto->getSelfInterfaceType()->isEqual(type)) return SelfReferenceInfo::forSelfRef(position); @@ -5153,6 +5136,11 @@ bool ProtocolDecl::isAvailableInExistential(const ValueDecl *decl) const { return true; } +bool ProtocolDecl::existentialTypeSupported() const { + return evaluateOrDefault(getASTContext().evaluator, + ExistentialTypeSupportedRequest{const_cast(this)}, true); +} + StringRef ProtocolDecl::getObjCRuntimeName( llvm::SmallVectorImpl &buffer) const { // If there is an 'objc' attribute with a name, use that name. diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index 8e21777014742..4c59adca8da4f 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -253,6 +253,31 @@ void ExistentialConformsToSelfRequest::cacheResult(bool value) const { decl->setCachedExistentialConformsToSelf(value); } +//----------------------------------------------------------------------------// +// existentialTypeSupported computation. +//----------------------------------------------------------------------------// + +void ExistentialTypeSupportedRequest::diagnoseCycle(DiagnosticEngine &diags) const { + auto decl = std::get<0>(getStorage()); + diags.diagnose(decl, diag::circular_protocol_def, decl->getName()); +} + +void ExistentialTypeSupportedRequest::noteCycleStep(DiagnosticEngine &diags) const { + auto requirement = std::get<0>(getStorage()); + diags.diagnose(requirement, diag::kind_declname_declared_here, + DescriptiveDeclKind::Protocol, requirement->getName()); +} + +Optional ExistentialTypeSupportedRequest::getCachedResult() const { + auto decl = std::get<0>(getStorage()); + return decl->getCachedExistentialTypeSupported(); +} + +void ExistentialTypeSupportedRequest::cacheResult(bool value) const { + auto decl = std::get<0>(getStorage()); + decl->setCachedExistentialTypeSupported(value); +} + //----------------------------------------------------------------------------// // isFinal computation. //----------------------------------------------------------------------------// diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 17ef27b6cc133..5a3a5824c5a16 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -7322,7 +7322,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, // Dig out the instance type and figure out what members of the instance type // we are going to see. auto baseTy = candidate.getBaseType(); - const auto baseObjTy = baseTy->getRValueType(); + auto baseObjTy = baseTy->getRValueType(); bool hasInstanceMembers = false; bool hasInstanceMethods = false; @@ -7369,6 +7369,18 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, hasInstanceMethods = true; } + // If our base is an existential type, we can't make use of any + // member whose signature involves associated types. + if (instanceTy->isExistentialType()) { + if (auto *proto = decl->getDeclContext()->getSelfProtocolDecl()) { + if (!proto->isAvailableInExistential(decl)) { + result.addUnviable(candidate, + MemberLookupResult::UR_UnavailableInExistential); + return; + } + } + } + // If the invocation's argument expression has a favored type, // use that information to determine whether a specific overload for // the candidate should be favored. @@ -7388,20 +7400,6 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, } } - const auto isUnsupportedExistentialMemberAccess = [&] { - // If our base is an existential type, we can't make use of any - // member whose signature involves associated types. - if (instanceTy->isExistentialType()) { - if (auto *proto = decl->getDeclContext()->getSelfProtocolDecl()) { - if (!proto->isAvailableInExistential(decl)) { - return true; - } - } - } - - return false; - }; - // See if we have an instance method, instance member or static method, // and check if it can be accessed on our base type. @@ -7415,35 +7413,20 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, ? candidate : OverloadChoice(instanceTy, decl, FunctionRefKind::SingleApply); - - const bool invalidMethodRef = isa(decl) && !hasInstanceMethods; - const bool invalidMemberRef = !isa(decl) && !hasInstanceMembers; - - if (invalidMethodRef || invalidMemberRef) { - // If this is definitely an invalid way to reference a method or member - // on the metatype, let's stop here. - result.addUnviable(choice, - MemberLookupResult::UR_InstanceMemberOnType); - return; - } else if (isUnsupportedExistentialMemberAccess()) { - // If the member reference itself is legal, but it turns out to be an - // unsupported existential member access, do not make further - // assumptions about the correctness of a potential call -- let - // the unsupported member access error prevail. - result.addUnviable(candidate, - MemberLookupResult::UR_UnavailableInExistential); + // If this is an instance member referenced from metatype + // let's add unviable result to the set because it could be + // either curried reference or an invalid call. + // + // New candidate shouldn't affect performance because such + // choice would only be attempted when solver is in diagnostic mode. + result.addUnviable(choice, MemberLookupResult::UR_InstanceMemberOnType); + + bool invalidMethodRef = isa(decl) && !hasInstanceMethods; + bool invalidMemberRef = !isa(decl) && !hasInstanceMembers; + // If this is definitely an invalid way to reference a method or member + // on the metatype, let's stop here. + if (invalidMethodRef || invalidMemberRef) return; - } else { - // Otherwise, still add an unviable result to the set, because it - // could be an invalid call that was supposed to be performed on an - // instance of the type. - // - // New candidate shouldn't affect performance because such - // choice would only be attempted when solver is in diagnostic mode. - result.addUnviable(choice, - MemberLookupResult::UR_InstanceMemberOnType); - - } } // If the underlying type of a typealias is fully concrete, it is legal @@ -7494,12 +7477,6 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, } } - if (isUnsupportedExistentialMemberAccess()) { - result.addUnviable(candidate, - MemberLookupResult::UR_UnavailableInExistential); - return; - } - // If we have an rvalue base, make sure that the result isn't 'mutating' // (only valid on lvalues). if (!baseTy->is() && diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 28fdbcdc60cde..8e425b4d589f5 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -3329,6 +3329,8 @@ static void checkSwitch(ASTContext &ctx, const SwitchStmt *stmt) { // We want to warn about "case .Foo, .Bar where 1 != 100:" since the where // clause only applies to the second case, and this is surprising. for (auto cs : stmt->getCases()) { + TypeChecker::checkUnsupportedProtocolType(ctx, cs); + // The case statement can have multiple case items, each can have a where. // If we find a "where", and there is a preceding item without a where, and // if they are on the same source line, then warn. @@ -4745,6 +4747,8 @@ void swift::performSyntacticExprDiagnostics(const Expr *E, void swift::performStmtDiagnostics(const Stmt *S, DeclContext *DC) { auto &ctx = DC->getASTContext(); + TypeChecker::checkUnsupportedProtocolType(ctx, const_cast(S)); + if (auto switchStmt = dyn_cast(S)) checkSwitch(ctx, switchStmt); diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 8404c66777501..873e93b0ea98a 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -672,6 +672,34 @@ ExistentialConformsToSelfRequest::evaluate(Evaluator &evaluator, return true; } +bool +ExistentialTypeSupportedRequest::evaluate(Evaluator &evaluator, + ProtocolDecl *decl) const { + // ObjC protocols can always be existential. + if (decl->isObjC()) + return true; + + for (auto member : decl->getMembers()) { + // Existential types cannot be used if the protocol has an associated type. + if (isa(member)) + return false; + + // For value members, look at their type signatures. + if (auto valueMember = dyn_cast(member)) { + if (!decl->isAvailableInExistential(valueMember)) + return false; + } + } + + // Check whether all of the inherited protocols support existential types. + for (auto proto : decl->getInheritedProtocols()) { + if (!proto->existentialTypeSupported()) + return false; + } + + return true; +} + bool IsFinalRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const { if (isa(decl)) diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 67b18808e70c6..35b646516e46b 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1659,6 +1659,8 @@ class DeclChecker : public DeclVisitor { DeclVisitor::visit(decl); + TypeChecker::checkUnsupportedProtocolType(decl); + if (auto VD = dyn_cast(decl)) { auto &Context = getASTContext(); TypeChecker::checkForForbiddenPrefix(Context, VD->getBaseName()); diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 078cd050f5ef8..e9ea56b2187ed 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -3949,6 +3949,159 @@ Type TypeChecker::substMemberTypeWithBase(ModuleDecl *module, return resultType; } +namespace { + +class UnsupportedProtocolVisitor + : public TypeReprVisitor, public ASTWalker +{ + ASTContext &Ctx; + bool checkStatements; + bool hitTopStmt; + +public: + UnsupportedProtocolVisitor(ASTContext &ctx, bool checkStatements) + : Ctx(ctx), checkStatements(checkStatements), hitTopStmt(false) { } + + bool walkToTypeReprPre(TypeRepr *T) override { + if (T->isInvalid()) + return false; + if (auto compound = dyn_cast(T)) { + // Only visit the last component to check, because nested typealiases in + // existentials are okay. + visit(compound->getComponentRange().back()); + return false; + } + // Arbitrary protocol constraints are OK on opaque types. + if (isa(T)) + return false; + + visit(T); + return true; + } + + std::pair walkToStmtPre(Stmt *S) override { + if (checkStatements && !hitTopStmt) { + hitTopStmt = true; + return { true, S }; + } + + return { false, S }; + } + + bool walkToDeclPre(Decl *D) override { + return !checkStatements; + } + + void visitTypeRepr(TypeRepr *T) { + // Do nothing for all TypeReprs except the ones listed below. + } + + void visitIdentTypeRepr(IdentTypeRepr *T) { + if (T->isInvalid()) + return; + + auto comp = T->getComponentRange().back(); + if (auto *proto = dyn_cast_or_null(comp->getBoundDecl())) { + if (!proto->existentialTypeSupported()) { + Ctx.Diags.diagnose(comp->getNameLoc(), + diag::unsupported_existential_type, + proto->getName()); + T->setInvalid(); + } + } else if (auto *alias = dyn_cast_or_null(comp->getBoundDecl())) { + auto type = Type(alias->getDeclaredInterfaceType()->getDesugaredType()); + type.findIf([&](Type type) -> bool { + if (T->isInvalid()) + return false; + if (type->isExistentialType()) { + auto layout = type->getExistentialLayout(); + for (auto *proto : layout.getProtocols()) { + auto *protoDecl = proto->getDecl(); + if (protoDecl->existentialTypeSupported()) + continue; + + Ctx.Diags.diagnose(comp->getNameLoc(), + diag::unsupported_existential_type, + protoDecl->getName()); + T->setInvalid(); + } + } + return false; + }); + } + } + + void visitRequirements(ArrayRef reqts) { + for (auto reqt : reqts) { + if (reqt.getKind() == RequirementReprKind::SameType) { + if (auto *repr = reqt.getFirstTypeRepr()) + repr->walk(*this); + if (auto *repr = reqt.getSecondTypeRepr()) + repr->walk(*this); + } + } + } +}; + +} // end anonymous namespace + +void TypeChecker::checkUnsupportedProtocolType(Decl *decl) { + if (!decl || decl->isInvalid()) + return; + + auto &ctx = decl->getASTContext(); + if (auto *protocolDecl = dyn_cast(decl)) { + checkUnsupportedProtocolType(ctx, protocolDecl->getTrailingWhereClause()); + } else if (auto *genericDecl = dyn_cast(decl)) { + checkUnsupportedProtocolType(ctx, genericDecl->getGenericParams()); + checkUnsupportedProtocolType(ctx, genericDecl->getTrailingWhereClause()); + } else if (auto *assocType = dyn_cast(decl)) { + checkUnsupportedProtocolType(ctx, assocType->getTrailingWhereClause()); + } else if (auto *extDecl = dyn_cast(decl)) { + checkUnsupportedProtocolType(ctx, extDecl->getTrailingWhereClause()); + } else if (auto *subscriptDecl = dyn_cast(decl)) { + checkUnsupportedProtocolType(ctx, subscriptDecl->getGenericParams()); + checkUnsupportedProtocolType(ctx, subscriptDecl->getTrailingWhereClause()); + } else if (auto *funcDecl = dyn_cast(decl)) { + if (!isa(funcDecl)) { + checkUnsupportedProtocolType(ctx, funcDecl->getGenericParams()); + checkUnsupportedProtocolType(ctx, funcDecl->getTrailingWhereClause()); + } + } + + if (isa(decl) || isa(decl)) + return; + + UnsupportedProtocolVisitor visitor(ctx, /*checkStatements=*/false); + decl->walk(visitor); +} + +void TypeChecker::checkUnsupportedProtocolType(ASTContext &ctx, Stmt *stmt) { + if (!stmt) + return; + + UnsupportedProtocolVisitor visitor(ctx, /*checkStatements=*/true); + stmt->walk(visitor); +} + +void TypeChecker::checkUnsupportedProtocolType( + ASTContext &ctx, TrailingWhereClause *whereClause) { + if (whereClause == nullptr) + return; + + UnsupportedProtocolVisitor visitor(ctx, /*checkStatements=*/false); + visitor.visitRequirements(whereClause->getRequirements()); +} + +void TypeChecker::checkUnsupportedProtocolType( + ASTContext &ctx, GenericParamList *genericParams) { + if (genericParams == nullptr) + return; + + UnsupportedProtocolVisitor visitor(ctx, /*checkStatements=*/false); + visitor.visitRequirements(genericParams->getRequirements()); +} + Type CustomAttrTypeRequest::evaluate(Evaluator &eval, CustomAttr *attr, DeclContext *dc, CustomAttrTypeKind typeKind) const { diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index 027a8afda44f2..d89144a636847 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -242,6 +242,22 @@ Type getOptionalType(SourceLoc loc, Type elementType); Expr *resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *Context, bool replaceInvalidRefsWithErrors); +/// Check for unsupported protocol types in the given declaration. +void checkUnsupportedProtocolType(Decl *decl); + +/// Check for unsupported protocol types in the given statement. +void checkUnsupportedProtocolType(ASTContext &ctx, Stmt *stmt); + +/// Check for unsupported protocol types in the given generic requirement +/// list. +void checkUnsupportedProtocolType(ASTContext &ctx, + TrailingWhereClause *whereClause); + +/// Check for unsupported protocol types in the given generic requirement +/// list. +void checkUnsupportedProtocolType(ASTContext &ctx, + GenericParamList *genericParams); + /// Substitute the given base type into the type of the given nested type, /// producing the effective type that the nested type will have. /// diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 3dff7b9d2fda8..1c4aab3483a5a 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -3561,13 +3561,14 @@ class DeclDeserializer { StringRef blobData) { IdentifierID nameID; DeclContextID contextID; - bool isImplicit, isClassBounded, isObjC; + bool isImplicit, isClassBounded, isObjC, existentialTypeSupported; uint8_t rawAccessLevel; unsigned numInheritedTypes; ArrayRef rawInheritedAndDependencyIDs; decls_block::ProtocolLayout::readRecord(scratch, nameID, contextID, isImplicit, isClassBounded, isObjC, + existentialTypeSupported, rawAccessLevel, numInheritedTypes, rawInheritedAndDependencyIDs); @@ -3593,6 +3594,8 @@ class DeclDeserializer { ctx.evaluator.cacheOutput(ProtocolRequiresClassRequest{proto}, std::move(isClassBounded)); + ctx.evaluator.cacheOutput(ExistentialTypeSupportedRequest{proto}, + std::move(existentialTypeSupported)); if (auto accessLevel = getActualAccessLevel(rawAccessLevel)) proto->setAccess(*accessLevel); diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index e2165a62c24f2..f0bc0bf3666b7 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -1257,6 +1257,7 @@ namespace decls_block { BCFixed<1>, // implicit flag BCFixed<1>, // class-bounded? BCFixed<1>, // objc? + BCFixed<1>, // existential-type-supported? AccessLevelField, // access level BCVBR<4>, // number of inherited types BCArray // inherited types, followed by dependency types diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index b326e40795fdf..0b8c74577c983 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -3545,6 +3545,7 @@ class Serializer::DeclSerializer : public DeclVisitor { const_cast(proto) ->requiresClass(), proto->isObjC(), + proto->existentialTypeSupported(), rawAccessLevel, numInherited, inheritedAndDependencyTypes); diff --git a/test/Constraints/static_members_on_protocol_in_generic_context.swift b/test/Constraints/static_members_on_protocol_in_generic_context.swift index 0516e08d92dc4..d9f342729509a 100644 --- a/test/Constraints/static_members_on_protocol_in_generic_context.swift +++ b/test/Constraints/static_members_on_protocol_in_generic_context.swift @@ -265,6 +265,24 @@ test_combo(.genericWithReqs([42])) test_combo(.genericWithReqs(())) // expected-error@-1 {{contextual member reference to static method 'genericWithReqs' requires 'Self' constraint in the protocol extension}} +protocol Z { + associatedtype T = Int + + static var prop: T { get } +} + +extension Z { + static func method() -> T { fatalError() } +} + +_ = Z.prop +// expected-error@-1 {{member 'prop' cannot be used on value of protocol type 'Z.Protocol'; use a generic constraint instead}} +// expected-error@-2 {{protocol 'Z' can only be used as a generic constraint because it has Self or associated type requirements}} + +_ = Z.method() +// expected-error@-1 {{member 'method' cannot be used on value of protocol type 'Z.Protocol'; use a generic constraint instead}} +// expected-error@-2 {{protocol 'Z' can only be used as a generic constraint because it has Self or associated type requirements}} + protocol TestWithAssoc { associatedtype U } diff --git a/test/Generics/function_defs.swift b/test/Generics/function_defs.swift index 8b5d8499ebfa3..5b83dba7d8c0c 100644 --- a/test/Generics/function_defs.swift +++ b/test/Generics/function_defs.swift @@ -34,7 +34,7 @@ func min(_ x: T, y: T) -> T { //===----------------------------------------------------------------------===// func existential(_ t1: T, t2: T, u: U) { - var eqComp : EqualComparable = t1 // Ok + var eqComp : EqualComparable = t1 // expected-error{{protocol 'EqualComparable' can only be used as a generic constraint}} eqComp = u if t1.isEqual(eqComp) {} // expected-error{{cannot convert value of type 'EqualComparable' to expected argument type 'T'}} if eqComp.isEqual(t2) {} // expected-error{{member 'isEqual' cannot be used on value of protocol type 'EqualComparable'; use a generic constraint instead}} @@ -49,11 +49,20 @@ func otherExistential(_ t1: T) { otherEqComp = t1 // expected-error{{value of type 'T' does not conform to 'OtherEqualComparable' in assignment}} _ = otherEqComp - var otherEqComp2 : OtherEqualComparable // Ok + var otherEqComp2 : OtherEqualComparable // expected-error{{protocol 'OtherEqualComparable' can only be used as a generic constraint}} otherEqComp2 = t1 // expected-error{{value of type 'T' does not conform to 'OtherEqualComparable' in assignment}} _ = otherEqComp2 - _ = t1 as EqualComparable & OtherEqualComparable // expected-error{{value of type 'T' does not conform to 'EqualComparable & OtherEqualComparable' in coercion}} + _ = t1 as EqualComparable & OtherEqualComparable // expected-error{{value of type 'T' does not conform to 'EqualComparable & OtherEqualComparable' in coercion}} expected-error{{protocol 'OtherEqualComparable' can only be used as a generic constraint}} expected-error{{protocol 'EqualComparable' can only be used as a generic constraint}} +} + +protocol Runcible { + func runce(_ x: A) + func spoon(_ x: Self) +} + +func testRuncible(_ x: Runcible) { // expected-error{{protocol 'Runcible' can only be used as a generic constraint}} + x.runce(5) } //===----------------------------------------------------------------------===// diff --git a/test/Sema/existential_nested_type.swift b/test/Sema/existential_nested_type.swift new file mode 100644 index 0000000000000..8189415c1f70e --- /dev/null +++ b/test/Sema/existential_nested_type.swift @@ -0,0 +1,24 @@ +// RUN: %target-swift-frontend -typecheck -verify -swift-version 4 %s + +// rdar://29605388 -- Swift 3 admitted opening an existential type with +// associated types in one case. + +// See test/IRGen/existential_nested_type.swift for the Swift 3 test. + +protocol HasAssoc { + associatedtype A +} + +enum MyError : Error { + case bad(Any) +} + +func checkIt(_ js: Any) throws { + switch js { + case let dbl as HasAssoc: // expected-error {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} + throw MyError.bad(dbl) + + default: + fatalError("wrong") + } +} diff --git a/test/decl/nested/protocol.swift b/test/decl/nested/protocol.swift index ab0427513619a..2ccc15b74e9a3 100644 --- a/test/decl/nested/protocol.swift +++ b/test/decl/nested/protocol.swift @@ -31,7 +31,8 @@ protocol OuterProtocol { struct ConformsToOuterProtocol : OuterProtocol { typealias Hen = Int - func f() { let _ = InnerProtocol.self } // Ok + func f() { let _ = InnerProtocol.self } + // expected-error@-1 {{protocol 'InnerProtocol' can only be used as a generic constraint because it has Self or associated type requirements}} } protocol Racoon { diff --git a/test/decl/nested/type_in_function.swift b/test/decl/nested/type_in_function.swift index 3908dad939434..7fa1c325d4b60 100644 --- a/test/decl/nested/type_in_function.swift +++ b/test/decl/nested/type_in_function.swift @@ -135,6 +135,20 @@ func genericFunction(t: T) { // expected-error@-2 {{'Second' inherits from itself}} } +// Spurious "Self or associated type requirements" diagnostic. +protocol ProtoWithAssocType { + associatedtype T = Int +} + +func freeFunction() { + struct ConformingType : ProtoWithAssocType { + typealias T = Int + + func method() -> ProtoWithAssocType {} + // expected-error@-1 {{can only be used as a generic constraint because it has Self or associated type requirements}} + } +} + // Superclass lookup archetype vs interface type mixup class Generic { struct Nested {} diff --git a/test/decl/protocol/conforms/inherited.swift b/test/decl/protocol/conforms/inherited.swift index 33e50e5ee418b..75c4c5de1aa21 100644 --- a/test/decl/protocol/conforms/inherited.swift +++ b/test/decl/protocol/conforms/inherited.swift @@ -167,13 +167,13 @@ class B : A { } func testB(_ b: B) { - var _: P1 = b - var _: P4 = b + var _: P1 = b // expected-error{{has Self or associated type requirements}} + var _: P4 = b // expected-error{{has Self or associated type requirements}} var _: P5 = b var _: P6 = b - var _: P7 = b - var _: P8 = b - var _: P9 = b + var _: P7 = b // expected-error{{has Self or associated type requirements}} + var _: P8 = b // okay + var _: P9 = b // expected-error{{has Self or associated type requirements}} } // Class A5 conforms to P5 in an inheritable manner. diff --git a/test/decl/protocol/protocols.swift b/test/decl/protocol/protocols.swift index 6689695102b62..0a2d9c5e48b39 100644 --- a/test/decl/protocol/protocols.swift +++ b/test/decl/protocol/protocols.swift @@ -102,10 +102,10 @@ struct DoesNotConform : Up { // Circular protocols protocol CircleMiddle : CircleStart { func circle_middle() } // expected-error {{protocol 'CircleMiddle' refines itself}} -// expected-note@-1 {{protocol 'CircleMiddle' declared here}} -protocol CircleStart : CircleEnd { func circle_start() } // expected-error {{protocol 'CircleStart' refines itself}} +// expected-note@-1 2 {{protocol 'CircleMiddle' declared here}} +protocol CircleStart : CircleEnd { func circle_start() } // expected-error 2 {{protocol 'CircleStart' refines itself}} // expected-note@-1 {{protocol 'CircleStart' declared here}} -protocol CircleEnd : CircleMiddle { func circle_end()} // expected-note 2 {{protocol 'CircleEnd' declared here}} +protocol CircleEnd : CircleMiddle { func circle_end()} // expected-note 3 {{protocol 'CircleEnd' declared here}} protocol CircleEntry : CircleTrivial { } protocol CircleTrivial : CircleTrivial { } // expected-error {{protocol 'CircleTrivial' refines itself}} @@ -263,6 +263,55 @@ struct WrongIsEqual : IsEqualComparable { // expected-error{{type 'WrongIsEqual' func isEqual(other: Int) -> Bool {} // expected-note{{candidate has non-matching type '(Int) -> Bool'}} } +//===----------------------------------------------------------------------===// +// Using values of existential type. +//===----------------------------------------------------------------------===// + +func existentialSequence(_ e: Sequence) { // expected-error{{has Self or associated type requirements}} + var x = e.makeIterator() // expected-error{{member 'makeIterator' cannot be used on value of protocol type 'Sequence'; use a generic constraint instead}} + x.next() + x.nonexistent() +} + +protocol HasSequenceAndStream { + associatedtype R : IteratorProtocol, Sequence + func getR() -> R +} + +func existentialSequenceAndStreamType(_ h: HasSequenceAndStream) { // expected-error{{has Self or associated type requirements}} + // FIXME: Crummy diagnostics. + var x = h.getR() // expected-error{{member 'getR' cannot be used on value of protocol type 'HasSequenceAndStream'; use a generic constraint instead}} + x.makeIterator() + x.next() + + x.nonexistent() +} + +//===----------------------------------------------------------------------===// +// Subscripting +//===----------------------------------------------------------------------===// +protocol IntIntSubscriptable { + subscript (i: Int) -> Int { get } +} + +protocol IntSubscriptable { + associatedtype Element + subscript (i: Int) -> Element { get } +} + +struct DictionaryIntInt { + subscript (i: Int) -> Int { + get { + return i + } + } +} + +func testSubscripting(_ iis: IntIntSubscriptable, i_s: IntSubscriptable) { // expected-error{{has Self or associated type requirements}} + var i: Int = iis[17] + var i2 = i_s[17] // expected-error{{member 'subscript' cannot be used on value of protocol type 'IntSubscriptable'; use a generic constraint instead}} +} + //===----------------------------------------------------------------------===// // Static methods //===----------------------------------------------------------------------===// @@ -439,18 +488,18 @@ func g(_ x : T) { class C3 : P1 {} // expected-error{{type 'C3' does not conform to protocol 'P1'}} func h(_ x : T) { - _ = x as P1 + _ = x as P1 // expected-error{{protocol 'P1' can only be used as a generic constraint because it has Self or associated type requirements}} } func i(_ x : T?) -> Bool { - return x is P1 + return x is P1 // expected-error{{protocol 'P1' can only be used as a generic constraint because it has Self or associated type requirements}} // FIXME: Bogus diagnostic. See SR-11920. // expected-warning@-2 {{checking a value with optional type 'T?' against dynamic type 'P1' succeeds whenever the value is non-nil; did you mean to use '!= nil'?}} } func j(_ x : C1) -> Bool { - return x is P1 + return x is P1 // expected-error{{protocol 'P1' can only be used as a generic constraint because it has Self or associated type requirements}} } func k(_ x : C1?) -> Bool { - return x is P1 + return x is P1 // expected-error{{protocol 'P1' can only be used as a generic constraint because it has Self or associated type requirements}} } diff --git a/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift deleted file mode 100644 index a82f86b0d3aa9..0000000000000 --- a/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift +++ /dev/null @@ -1,523 +0,0 @@ -// RUN: %target-typecheck-verify-swift - -//===----------------------------------------------------------------------===// -// Use of protocols with Self or associated type requirements -//===----------------------------------------------------------------------===// - -struct G { - class Inner {} - struct InnerG {} -} -class C {} - -protocol P1 { - associatedtype Q - - // Methods - func covariantSelfSimple() -> Self - func covariantSelfComplex(_: (Self) -> Void, - _: (Self?) -> Void, - _: (Array) -> Void, - _: (Array?>) -> Void - ) -> [String : () -> (Self, Self)] - func covariantAssocSimple() -> Q - func covariantAssocComplex(_: (Q) -> Void, - _: (Q?) -> Void, - _: (Array) -> Void, - _: (Array?>) -> Void - ) -> [String : () -> (Q, Q)] - - func contravariantSelf1(_: Self?) - func contravariantSelf2(_: () -> Self) - func contravariantSelf3(_: Array<() -> Self>) - func contravariantSelf4(_: [String : () -> Self]) - func contravariantSelf5(_: () -> (Self, Self)) - func contravariantSelf6(_: ((Self) -> Void) -> Void) - func contravariantSelf7() -> (Self) -> Void - func contravariantSelf8() -> Array<((Self) -> Void)?> - func contravariantSelf9(_: [String : (() -> Self)?]) - func contravariantSelf10() -> (Array<[String : Self??]>) -> Void - func contravariantAssoc1(_: Q?) - func contravariantAssoc2(_: () -> Q) - func contravariantAssoc3(_: Array<() -> Q>) - func contravariantAssoc4(_: [String : () -> Q]) - func contravariantAssoc5(_: () -> (Q, Q)) - func contravariantAssoc6(_: ((Q) -> Void) -> Void) - func contravariantAssoc7() -> (Q) -> Void - func contravariantAssoc8() -> Array<((Q) -> Void)?> - func contravariantAssoc9(_: [String : (() -> Q)?]) - func contravariantAssoc10() -> (Array<[String : Q??]>) -> Void - - func invariantSelf1(_: inout Self) - func invariantSelf2(_: (inout Self) -> Void) - func invariantSelf3(_: inout Array<() -> Self>) - func invariantSelf4(_: G) - func invariantSelf5() -> G - func invariantSelf6() -> G.Inner - func invariantSelf7(_: (G) -> Void) - func invariantSelf8(_: G<(Self) -> Void>) - func invariantSelf9(_: G<() -> Self>) - func invariantSelf10(_: P1 & C) - func invariantSelf11() -> G.InnerG - func invariantAssoc1(_: inout Q) - func invariantAssoc2(_: (inout Q) -> Void) - func invariantAssoc3(_: inout Array<() -> Q>) - func invariantAssoc4(_: G) - func invariantAssoc5() -> G - func invariantAssoc6() -> G.Inner - func invariantAssoc7(_: (G) -> Void) - func invariantAssoc8(_: G<(Q) -> Void>) - func invariantAssoc9(_: G<() -> Q>) - func invariantAssoc10(_: P1 & C) - func invariantAssoc11() -> G.InnerG - - // Properties - var covariantSelfPropSimple: Self { get } - var covariantSelfPropComplex: ( - _: (Self) -> Void, - _: (Self?) -> Void, - _: (Array) -> Void, - _: (Array?>) -> Void - ) -> [String : () -> (Self, Self)] { get } - var covariantAssocPropSimple: Q { get } - var covariantAssocPropComplex: ( - _: (Q) -> Void, - _: (Q?) -> Void, - _: (Array) -> Void, - _: (Array?>) -> Void - ) -> [String : () -> (Q, Q)] { get } - - var contravariantSelfProp1: (Self?) -> Void { get } - var contravariantSelfProp2: (() -> Self) -> Void { get } - var contravariantSelfProp3: (Array<() -> Self>) -> Void { get } - var contravariantSelfProp4: ([String : () -> Self]) -> Void { get } - var contravariantSelfProp5: (() -> (Self, Self)) -> Void { get } - var contravariantSelfProp6: (((Self) -> Void) -> Void) -> Void { get } - var contravariantSelfProp7: (Self) -> Void { get } - var contravariantSelfProp8: Array<((Self) -> Void)?> { get } - var contravariantSelfProp9: ([String : (() -> Self)?]) -> Void { get } - var contravariantSelfProp10: (Array<[String : Self??]>) -> Void { get } - var contravariantAssocProp1: (Q?) -> Void { get } - var contravariantAssocProp2: (() -> Q) -> Void { get } - var contravariantAssocProp3: (Array<() -> Q>) -> Void { get } - var contravariantAssocProp4: ([String : () -> Q]) -> Void { get } - var contravariantAssocProp5: (() -> (Q, Q)) -> Void { get } - var contravariantAssocProp6: (((Q) -> Void) -> Void) -> Void { get } - var contravariantAssocProp7: (Q) -> Void { get } - var contravariantAssocProp8: Array<((Q) -> Void)?> { get } - var contravariantAssocProp9: ([String : (() -> Q)?]) -> Void { get } - var contravariantAssocProp10: (Array<[String : Q??]>) -> Void { get } - - var invariantSelfProp1: (inout Self) -> Void { get } - var invariantSelfProp2: ((inout Self) -> Void) -> Void { get } - var invariantSelfProp3: (inout Array<() -> Self>) -> Void { get } - var invariantSelfProp4: (G) -> Void { get } - var invariantSelfProp5: G { get } - var invariantSelfProp6: G.Inner { get } - var invariantSelfProp7: ((G) -> Void) -> Void { get } - var invariantSelfProp8: (G<(Self) -> Void>) -> Void { get } - var invariantSelfProp9: (G<() -> Self>) -> Void { get } - var invariantSelfProp10: (P1 & C) -> Void { get } - var invariantSelfProp11: G.InnerG { get } - var invariantAssocProp1: (inout Q) -> Void { get } - var invariantAssocProp2: ((inout Q) -> Void) -> Void { get } - var invariantAssocProp3: (inout Array<() -> Q>) -> Void { get } - var invariantAssocProp4: (G) -> Void { get } - var invariantAssocProp5: G { get } - var invariantAssocProp6: G.Inner { get } - var invariantAssocProp7: ((G) -> Void) { get } - var invariantAssocProp8: (G<(Q) -> Void>) { get } - var invariantAssocProp9: (G<() -> Q>) -> Void { get } - var invariantAssocProp10: (P1 & C) -> Void { get } - var invariantAssocProp11: G.InnerG { get } - - // Subscripts - subscript(covariantSelfSubscriptSimple _: Void) -> Self { get } - subscript(covariantSelfSubscriptComplex _: (Self) -> Void, - _: (Self?) -> Void, - _: (Array) -> Void, - _: (Array?>) -> Void - ) -> [String : () -> (Self, Self)] { get } - subscript(covariantAssocSubscriptSimple _: Void) -> Q { get } - subscript(covariantAssocSubscriptComplex _: (Q) -> Void, - _: (Q?) -> Void, - _: (Array) -> Void, - _: (Array?>) -> Void - ) -> [String : () -> (Q, Q)] { get } - - subscript(contravariantSelfSubscript1 _: Self?) -> Void { get } - subscript(contravariantSelfSubscript2 _: () -> Self) -> Void { get } - subscript(contravariantSelfSubscript3 _: Array<() -> Self>) -> Void { get } - subscript(contravariantSelfSubscript4 _: [String : () -> Self]) -> Void { get } - subscript(contravariantSelfSubscript5 _: () -> (Self, Self)) -> Void { get } - subscript(contravariantSelfSubscript6 _: ((Self) -> Void) -> Void) -> Void { get } - subscript(contravariantSelfSubscript7 _: Void) -> (Self) -> Void { get } - subscript(contravariantSelfSubscript8 _: Void) -> Array<((Self) -> Void)?> { get } - subscript(contravariantSelfSubscript9 _: [String : (() -> Self)?]) -> Void { get } - subscript(contravariantSelfSubscript10 _: Void) -> (Array<[String : Self??]>) -> Void { get } - subscript(contravariantAssocSubscript1 _: Q?) -> Void { get } - subscript(contravariantAssocSubscript2 _: () -> Q) -> Void { get } - subscript(contravariantAssocSubscript3 _: Array<() -> Q>) -> Void { get } - subscript(contravariantAssocSubscript4 _: [String : () -> Q]) -> Void { get } - subscript(contravariantAssocSubscript5 _: () -> (Q, Q)) -> Void { get } - subscript(contravariantAssocSubscript6 _: ((Q) -> Void) -> Void) -> Void { get } - subscript(contravariantAssocSubscript7 _: Void) -> (Q) -> Void { get } - subscript(contravariantAssocSubscript8 _: Void) -> Array<((Q) -> Void)?> { get } - subscript(contravariantAssocSubscript9 _: [String : (() -> Q)?]) -> Void { get } - subscript(contravariantAssocSubscript10 _: Void) -> (Array<[String : Q??]>) -> Void { get } - - subscript(invariantSelfSubscript1 _: G) -> Void { get } - subscript(invariantSelfSubscript2 _: Void) -> G { get } - subscript(invariantSelfSubscript3 _: Void) -> G.Inner { get } - subscript(invariantSelfSubscript4 _: (G) -> Void) -> Void { get } - subscript(invariantSelfSubscript5 _: G<(Self) -> Void>) -> Void { get } - subscript(invariantSelfSubscript6 _: G<() -> Self>) -> Void { get } - subscript(invariantSelfSubscript7 _: P1 & C) -> Void { get } - subscript(invariantSelfSubscript8 _: Void) -> G.InnerG { get } - subscript(invariantAssocSubscript1 _: G) -> Void { get } - subscript(invariantAssocSubscript2 _: Void) -> G { get } - subscript(invariantAssocSubscript3 _: Void) -> G.Inner { get } - subscript(invariantAssocSubscript4 _: (G) -> Void) -> Void { get } - subscript(invariantAssocSubscript5 _: G<(Q) -> Void>) -> Void { get } - subscript(invariantAssocSubscript6 _: G<() -> Q>) -> Void { get } - subscript(invariantAssocSubscript7 _: P1 & C) -> Void { get } - subscript(invariantAssocSubscript8 _: Void) -> G.InnerG { get } -} -@available(macOS 10.15, *) -extension P1 { - func invariantSelf1_1() -> some P1 { self } - var invariantSelfProp1_1: some P1 { self } - subscript(invariantSelfSubscript1_1: Void) -> some P1 { self } -} - -do { - func testP1(arg: P1) { - _ = arg.covariantSelfSimple() // ok - let _: P1 = arg.covariantSelfSimple() // ok - _ = arg.covariantSelfComplex({ _ in }, { _ in }, { _ in }, { _ in }) // ok - let _: [String : () -> (P1, P1)] = arg.covariantSelfComplex( - { (x: P1) in }, - { (x: P1?) in }, - { (x: Array) in }, - { (x: Array?>) in } - ) // ok - arg.covariantAssocSimple // expected-error {{member 'covariantAssocSimple' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.covariantAssocComplex({ _ in }, { _ in }, { _ in }, { _ in }) // expected-error {{member 'covariantAssocComplex' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: expected-error@-1 {{unable to infer type of a closure parameter '_' in the current context}} - - _ = arg.covariantSelfPropSimple // ok - let _: P1 = arg.covariantSelfPropSimple // ok - _ = arg.covariantSelfPropComplex // ok - let _: ( - _: (P1) -> Void, - _: (P1?) -> Void, - _: (Array) -> Void, - _: (Array?>) -> Void - ) -> [String : () -> (P1, P1)] = arg.covariantSelfPropComplex // ok - arg.covariantAssocPropSimple // expected-error {{member 'covariantAssocPropSimple' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.covariantAssocPropComplex // expected-error {{member 'covariantAssocPropComplex' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - - _ = arg[covariantSelfSubscriptSimple: ()] // ok - let _: P1 = arg[covariantSelfSubscriptSimple: ()] // ok - _ = arg[covariantSelfSubscriptComplex: { _ in }, { _ in }, { _ in }, { _ in }] // ok - let _: [String : () -> (P1, P1)] = arg[ - covariantSelfSubscriptComplex: { (x: P1) in }, - { (x: P1?) in }, - { (x: Array) in }, - { (x: Array?>) in } - ] // ok - arg[covariantAssocSubscriptSimple: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg[covariantAssocSubscriptComplex: { _ in }, { _ in }, { _ in }, { _ in }] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - - arg.contravariantSelf1(0) // expected-error {{member 'contravariantSelf1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Silence these since we cannot make use of the member anyway. - // expected-error@-2 {{argument type 'Int' does not conform to expected type 'P1'}} - arg.contravariantSelf2(0) // expected-error {{member 'contravariantSelf2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> P1'}} - arg.contravariantSelf3(0) // expected-error {{member 'contravariantSelf3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'Array<() -> P1>'}} - arg.contravariantSelf4(0) // expected-error {{member 'contravariantSelf4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : () -> P1]'}} - arg.contravariantSelf5(0) // expected-error {{member 'contravariantSelf5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> (P1, P1)'}} - arg.contravariantSelf6(0) // expected-error {{member 'contravariantSelf6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '((P1) -> Void) -> Void'}} - arg.contravariantSelf7() // expected-error {{member 'contravariantSelf7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantSelf8() // expected-error {{member 'contravariantSelf8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantSelf9(0) // expected-error {{member 'contravariantSelf9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : (() -> P1)?]'}} - arg.contravariantSelf10() // expected-error {{member 'contravariantSelf10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantAssoc1(0) // expected-error {{member 'contravariantAssoc1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Silence these since we cannot make use of the member anyway. - // expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'P1.Q?'}} - arg.contravariantAssoc2(0) // expected-error {{member 'contravariantAssoc2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> P1.Q'}} - arg.contravariantAssoc3(0) // expected-error {{member 'contravariantAssoc3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'Array<() -> P1.Q>'}} - arg.contravariantAssoc4(0) // expected-error {{member 'contravariantAssoc4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : () -> P1.Q]'}} - arg.contravariantAssoc5(0) // expected-error {{member 'contravariantAssoc5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> (P1.Q, P1.Q)'}} - arg.contravariantAssoc6(0) // expected-error {{member 'contravariantAssoc6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '((P1.Q) -> Void) -> Void'}} - arg.contravariantAssoc7() // expected-error {{member 'contravariantAssoc7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantAssoc8() // expected-error {{member 'contravariantAssoc8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantAssoc9(0) // expected-error {{member 'contravariantAssoc9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : (() -> P1.Q)?]'}} - arg.contravariantAssoc10() // expected-error {{member 'contravariantAssoc10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - - - arg.invariantSelf1(0) // expected-error {{member 'invariantSelf1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Silence these since we cannot make use of the member anyway. - // expected-error@-2 {{argument type 'Int' does not conform to expected type 'P1'}} - if #available(macOS 10.15, *) { - arg.invariantSelf1_1() // expected-error {{member 'invariantSelf1_1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - } - arg.invariantSelf2(0) // expected-error {{member 'invariantSelf2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(inout P1) -> Void'}} - arg.invariantSelf3(0) // expected-error {{member 'invariantSelf3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'Array<() -> P1>'}} - arg.invariantSelf4(0) // expected-error {{member 'invariantSelf4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G'}} - arg.invariantSelf5() // expected-error {{member 'invariantSelf5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantSelf6() // expected-error {{member 'invariantSelf6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantSelf7(0) // expected-error {{member 'invariantSelf7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G) -> Void'}} - arg.invariantSelf8(0) // expected-error {{member 'invariantSelf8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1) -> Void>'}} - arg.invariantSelf9(0) // expected-error {{member 'invariantSelf9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1>'}} - arg.invariantSelf10(0) // expected-error {{member 'invariantSelf10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'C'}} - arg.invariantSelf11() // expected-error {{member 'invariantSelf11' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantAssoc1(0) // expected-error {{member 'invariantAssoc1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Silence these since we cannot make use of the member anyway. - // expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'P1.Q'}} - arg.invariantAssoc2(0) // expected-error {{member 'invariantAssoc2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(inout P1.Q) -> Void'}} - arg.invariantAssoc3(0) // expected-error {{member 'invariantAssoc3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'Array<() -> P1.Q>'}} - arg.invariantAssoc4(0) // expected-error {{member 'invariantAssoc4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G'}} - arg.invariantAssoc5() // expected-error {{member 'invariantAssoc5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantAssoc6() // expected-error {{member 'invariantAssoc6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantAssoc7(0) // expected-error {{member 'invariantAssoc7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G) -> Void'}} - arg.invariantAssoc8(0) // expected-error {{member 'invariantAssoc8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1.Q) -> Void>'}} - arg.invariantAssoc9(0) // expected-error {{member 'invariantAssoc9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1.Q>'}} - arg.invariantAssoc10(0) // expected-error {{member 'invariantAssoc10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'C'}} - arg.invariantAssoc11() // expected-error {{member 'invariantAssoc11' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - - arg.contravariantSelfProp1 // expected-error {{member 'contravariantSelfProp1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantSelfProp2 // expected-error {{member 'contravariantSelfProp2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantSelfProp3 // expected-error {{member 'contravariantSelfProp3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantSelfProp4 // expected-error {{member 'contravariantSelfProp4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantSelfProp5 // expected-error {{member 'contravariantSelfProp5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantSelfProp6 // expected-error {{member 'contravariantSelfProp6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantSelfProp7 // expected-error {{member 'contravariantSelfProp7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantSelfProp8 // expected-error {{member 'contravariantSelfProp8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantSelfProp9 // expected-error {{member 'contravariantSelfProp9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantSelfProp10 // expected-error {{member 'contravariantSelfProp10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantAssocProp1 // expected-error {{member 'contravariantAssocProp1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantAssocProp2 // expected-error {{member 'contravariantAssocProp2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantAssocProp3 // expected-error {{member 'contravariantAssocProp3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantAssocProp4 // expected-error {{member 'contravariantAssocProp4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantAssocProp5 // expected-error {{member 'contravariantAssocProp5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantAssocProp6 // expected-error {{member 'contravariantAssocProp6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantAssocProp7 // expected-error {{member 'contravariantAssocProp7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantAssocProp8 // expected-error {{member 'contravariantAssocProp8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantAssocProp9 // expected-error {{member 'contravariantAssocProp9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.contravariantAssocProp10 // expected-error {{member 'contravariantAssocProp10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - - arg.invariantSelfProp1 // expected-error {{member 'invariantSelfProp1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - if #available(macOS 10.15, *) { - arg.invariantSelfProp1_1 // expected-error {{member 'invariantSelfProp1_1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - } - arg.invariantSelfProp2 // expected-error {{member 'invariantSelfProp2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantSelfProp3 // expected-error {{member 'invariantSelfProp3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantSelfProp4 // expected-error {{member 'invariantSelfProp4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantSelfProp5 // expected-error {{member 'invariantSelfProp5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantSelfProp6 // expected-error {{member 'invariantSelfProp6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantSelfProp7 // expected-error {{member 'invariantSelfProp7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantSelfProp8 // expected-error {{member 'invariantSelfProp8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantSelfProp9 // expected-error {{member 'invariantSelfProp9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantSelfProp10 // expected-error {{member 'invariantSelfProp10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantSelfProp11 // expected-error {{member 'invariantSelfProp11' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantAssocProp1 // expected-error {{member 'invariantAssocProp1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantAssocProp2 // expected-error {{member 'invariantAssocProp2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantAssocProp3 // expected-error {{member 'invariantAssocProp3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantAssocProp4 // expected-error {{member 'invariantAssocProp4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantAssocProp5 // expected-error {{member 'invariantAssocProp5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantAssocProp6 // expected-error {{member 'invariantAssocProp6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantAssocProp7 // expected-error {{member 'invariantAssocProp7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantAssocProp8 // expected-error {{member 'invariantAssocProp8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantAssocProp9 // expected-error {{member 'invariantAssocProp9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantAssocProp10 // expected-error {{member 'invariantAssocProp10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg.invariantAssocProp11 // expected-error {{member 'invariantAssocProp11' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - - arg[contravariantSelfSubscript1: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Silence these since we cannot make use of the member anyway. - // expected-error@-2 {{argument type 'Int' does not conform to expected type 'P1'}} - arg[contravariantSelfSubscript2: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> P1'}} - arg[contravariantSelfSubscript3: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'Array<() -> P1>'}} - arg[contravariantSelfSubscript4: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : () -> P1]'}} - arg[contravariantSelfSubscript5: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> (P1, P1)'}} - arg[contravariantSelfSubscript6: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '((P1) -> Void) -> Void'}} - arg[contravariantSelfSubscript7: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg[contravariantSelfSubscript8: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg[contravariantSelfSubscript9: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : (() -> P1)?]'}} - arg[contravariantSelfSubscript10: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg[contravariantAssocSubscript1: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Silence these since we cannot make use of the member anyway. - // expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'P1.Q?'}} - arg[contravariantAssocSubscript2: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> P1.Q'}} - arg[contravariantAssocSubscript3: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'Array<() -> P1.Q>'}} - arg[contravariantAssocSubscript4: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : () -> P1.Q]'}} - arg[contravariantAssocSubscript5: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> (P1.Q, P1.Q)'}} - arg[contravariantAssocSubscript6: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '((P1.Q) -> Void) -> Void'}} - arg[contravariantAssocSubscript7: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg[contravariantAssocSubscript8: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg[contravariantAssocSubscript9: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : (() -> P1.Q)?]'}} - arg[contravariantAssocSubscript10: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - - arg[invariantSelfSubscript1: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Silence these since we cannot make use of the member anyway. - // expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'G'}} - arg[invariantSelfSubscript2: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg[invariantSelfSubscript3: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg[invariantSelfSubscript4: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G) -> Void'}} - arg[invariantSelfSubscript5: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1) -> Void>'}} - arg[invariantSelfSubscript6: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1>'}} - arg[invariantSelfSubscript7: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'C'}} - arg[invariantSelfSubscript8: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg[invariantAssocSubscript1: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Silence these since we cannot make use of the member anyway. - // expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'G'}} - arg[invariantAssocSubscript2: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg[invariantAssocSubscript3: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - arg[invariantAssocSubscript4: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G) -> Void'}} - arg[invariantAssocSubscript5: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1.Q) -> Void>'}} - arg[invariantAssocSubscript6: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1.Q>'}} - arg[invariantAssocSubscript7: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'C'}} - arg[invariantAssocSubscript8: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - } -} - -protocol P1_TypeMemberOnInstanceAndViceVersa { - static func static_covariantSelfMethod() -> Self - static var static_covariantSelfProp: Self { get } - static subscript(static_covariantSelfSubscript _: Void) -> Self { get } - - static func static_invariantSelfMethod() -> G - static var static_invariantSelfProp: G { get } - static subscript(static_invariantSelfSubscript _: Void) -> G { get } - - func covariantSelfMethod() -> Self - - func invariantSelfMethod() -> G - var invariantSelfProp: G { get } - subscript(invariantSelfSubscript _: Void) -> G { get } -} -do { - // Test that invalid reference errors prevail over unsupported existential - // member accesses. - func test(protoMeta: P1_TypeMemberOnInstanceAndViceVersa.Protocol, - existMeta: P1_TypeMemberOnInstanceAndViceVersa.Type, - instance: P1_TypeMemberOnInstanceAndViceVersa) { - // P1_TypeMemberOnInstanceAndViceVersa.Protocol - protoMeta.static_invariantSelfMethod() // expected-error {{static member 'static_invariantSelfMethod' cannot be used on protocol metatype 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'}} - protoMeta.static_invariantSelfProp // expected-error {{static member 'static_invariantSelfProp' cannot be used on protocol metatype 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'}} - protoMeta[static_invariantSelfSubscript: ()] // expected-error {{static member 'subscript' cannot be used on protocol metatype 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'}} - _ = protoMeta.covariantSelfMethod // ok - protoMeta.invariantSelfMethod // expected-error {{member 'invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} - protoMeta.invariantSelfProp // expected-error {{instance member 'invariantSelfProp' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}} - protoMeta[invariantSelfSubscript: ()] // expected-error {{instance member 'subscript' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}} - - // P1_TypeMemberOnInstanceAndViceVersa.Type - _ = existMeta.static_covariantSelfMethod // ok - _ = existMeta.static_covariantSelfProp // ok - _ = existMeta[static_covariantSelfSubscript: ()] // ok - existMeta.static_invariantSelfMethod // expected-error {{member 'static_invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} - existMeta.static_invariantSelfProp // expected-error {{member 'static_invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} - existMeta[static_invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} - existMeta.invariantSelfMethod // expected-error {{instance member 'invariantSelfMethod' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}} - existMeta.invariantSelfProp // expected-error {{instance member 'invariantSelfProp' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}} - existMeta[invariantSelfSubscript: ()] // expected-error {{instance member 'subscript' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}} - - // P1_TypeMemberOnInstanceAndViceVersa - instance.static_invariantSelfMethod // expected-error {{static member 'static_invariantSelfMethod' cannot be used on instance of type 'P1_TypeMemberOnInstanceAndViceVersa'}} - instance.static_invariantSelfProp // expected-error {{static member 'static_invariantSelfProp' cannot be used on instance of type 'P1_TypeMemberOnInstanceAndViceVersa'}} - instance[static_invariantSelfSubscript: ()] // expected-error {{static member 'subscript' cannot be used on instance of type 'P1_TypeMemberOnInstanceAndViceVersa'}} - } -} - -// Settable storage members with a 'Self' result type may not be used with an -// existential base. -protocol P2 { - subscript() -> Self { get set } - - var prop: Self { get set } -} -func takesP2(p2: P2) { - _ = p2[] - // expected-error@-1{{member 'subscript' cannot be used on value of protocol type 'P2'; use a generic constraint instead}} - _ = p2.prop - // expected-error@-1{{member 'prop' cannot be used on value of protocol type 'P2'; use a generic constraint instead}} -} - -protocol MiscTestsProto { - associatedtype Assoc - func runce(_: A) - func spoon(_: Self) - - associatedtype R : IteratorProtocol, Sequence - func getR() -> R - - subscript(intToAssoc _: Int) -> Assoc { get } - subscript(intToInt _: Int) -> Int { get } -} -do { - func miscTests(_ arg: MiscTestsProto) { // ok - arg.runce(5) - - do { - // FIXME: Crummy diagnostics. - var x = arg.getR() // expected-error{{member 'getR' cannot be used on value of protocol type 'MiscTestsProto'; use a generic constraint instead}} - x.makeIterator() - x.next() - x.nonexistent() - } - - var _: Int = arg[intToInt: 17] - _ = arg[intToAssoc: 17] // expected-error{{member 'subscript' cannot be used on value of protocol type 'MiscTestsProto'; use a generic constraint instead}} - } - - func existentialSequence(_ e: Sequence) { - var x = e.makeIterator() // expected-error{{member 'makeIterator' cannot be used on value of protocol type 'Sequence'; use a generic constraint instead}} - x.next() - x.nonexistent() - } -} diff --git a/test/decl/protocol/protocols_with_self_or_assoc_reqs_executable.swift b/test/decl/protocol/protocols_with_self_or_assoc_reqs_executable.swift deleted file mode 100644 index 58aa147a3ebe9..0000000000000 --- a/test/decl/protocol/protocols_with_self_or_assoc_reqs_executable.swift +++ /dev/null @@ -1,107 +0,0 @@ -// RUN: %target-run-simple-swift -// REQUIRES: executable_test - -import StdlibUnittest - -let Tests = TestSuite(#file) - -protocol P { - associatedtype Assoc = Self - - func getString() -> String - - func covariantSelfSimple() -> Self - func covariantSelfArray() -> Array - func covariantSelfDictionary() -> [String : Self] - func covariantSelfClosure(_: (Self) -> Void) - - var covariantSelfPropSimple: Self { get } - var covariantSelfPropArray: Array { get } - var covariantSelfPropDictionary: [String : Self] { get } - var covariantSelfPropClosure: ((Self) -> Void) -> Void { get } - - subscript(covariantSelfSubscriptSimple _: Void) -> Self { get } - subscript(covariantSelfSubscriptArray _: Void) -> Array { get } - subscript(covariantSelfSubscriptDictionary _: Void) -> [String : Self] { get } - subscript(covariantSelfSubscriptClosure _: (Self) -> Void) -> Void { get } -} -extension P { - func covariantSelfSimple() -> Self { self } - func covariantSelfArray() -> Array { [self] } - func covariantSelfDictionary() -> [String : Self] { [#file : self] } - func covariantSelfClosure(_ arg: (Self) -> Void) { arg(self) } - - var covariantSelfPropSimple: Self { self } - var covariantSelfPropArray: Array { [self] } - var covariantSelfPropDictionary: [String : Self] { [#file : self] } - var covariantSelfPropClosure: ((Self) -> Void) -> Void { { $0(self) } } - - subscript(covariantSelfSubscriptSimple _: Void) -> Self { self } - subscript(covariantSelfSubscriptArray _: Void) -> Array { [self] } - subscript(covariantSelfSubscriptDictionary _: Void) -> [String : Self] { [#file : self] } - subscript(covariantSelfSubscriptClosure arg: (Self) -> Void) -> Void { arg(self) } -} - -Tests.test("Basic") { - let collection: Collection = [0, 0, 0] - - expectEqual(3, collection.count) -} - -Tests.test("Covariant 'Self' erasure") { - struct S: P { - static let str = "Success" - func getString() -> String { Self.str } - } - - let p: P = S() - - // Partial Application - do { - let covariantSelfSimplePartialApp = p.covariantSelfSimple - let covariantSelfArrayPartialApp = p.covariantSelfArray - let covariantSelfDictionaryPartialApp = p.covariantSelfDictionary - let covariantSelfClosurePartialApp = p.covariantSelfClosure - - expectEqual(S.str, covariantSelfSimplePartialApp().getString()) - expectEqual(S.str, covariantSelfArrayPartialApp().first.unsafelyUnwrapped.getString()) - expectEqual(S.str, covariantSelfDictionaryPartialApp()[#file].unsafelyUnwrapped.getString()) - covariantSelfClosurePartialApp { expectEqual(S.str, $0.getString()) } - } - - // Instance method reference on metatype - do { - let covariantSelfSimpleRef = P.covariantSelfSimple - let covariantSelfArrayRef = P.covariantSelfArray - let covariantSelfDictionaryRef = P.covariantSelfDictionary - let covariantSelfClosureRef = P.covariantSelfClosure - - expectEqual(S.str, covariantSelfSimpleRef(p)().getString()) - expectEqual(S.str, covariantSelfArrayRef(p)().first.unsafelyUnwrapped.getString()) - expectEqual(S.str, covariantSelfDictionaryRef(p)()[#file].unsafelyUnwrapped.getString()) - covariantSelfClosureRef(p)({ expectEqual(S.str, $0.getString()) }) - } - - // Regular calls - expectEqual(S.str, p.covariantSelfSimple().getString()) - expectEqual(S.str, p.covariantSelfArray().first.unsafelyUnwrapped.getString()) - expectEqual(S.str, p.covariantSelfDictionary()[#file].unsafelyUnwrapped.getString()) - p.covariantSelfClosure { expectEqual(S.str, $0.getString()) } - - expectEqual(S.str, p.covariantSelfPropSimple.getString()) - expectEqual(S.str, p.covariantSelfPropArray.first.unsafelyUnwrapped.getString()) - expectEqual(S.str, p.covariantSelfPropDictionary[#file].unsafelyUnwrapped.getString()) - p.covariantSelfPropClosure { expectEqual(S.str, $0.getString()) } - - expectEqual(S.str, p[covariantSelfSubscriptSimple: ()].getString()) - expectEqual(S.str, p[covariantSelfSubscriptArray: ()].first.unsafelyUnwrapped.getString()) - expectEqual(S.str, p[covariantSelfSubscriptDictionary: ()][#file].unsafelyUnwrapped.getString()) - p[covariantSelfSubscriptClosure: { expectEqual(S.str, $0.getString()) }] - - expectEqual(S.str, (S() as P).getString()) - - expectEqual(true, p is P) - expectEqual(true, S() is P) -} - -runAllTests() diff --git a/test/decl/protocol/recursive_requirement.swift b/test/decl/protocol/recursive_requirement.swift index c99dadbb6b4bd..fd6ee93d412ae 100644 --- a/test/decl/protocol/recursive_requirement.swift +++ b/test/decl/protocol/recursive_requirement.swift @@ -91,7 +91,7 @@ protocol AsExistentialB { } protocol AsExistentialAssocTypeA { - var delegate : AsExistentialAssocTypeB? { get } + var delegate : AsExistentialAssocTypeB? { get } // expected-error {{protocol 'AsExistentialAssocTypeB' can only be used as a generic constraint because it has Self or associated type requirements}} } protocol AsExistentialAssocTypeB { func aMethod(_ object : AsExistentialAssocTypeA) @@ -103,7 +103,7 @@ protocol AsExistentialAssocTypeAgainA { associatedtype Bar } protocol AsExistentialAssocTypeAgainB { - func aMethod(_ object : AsExistentialAssocTypeAgainA) + func aMethod(_ object : AsExistentialAssocTypeAgainA) // expected-error {{protocol 'AsExistentialAssocTypeAgainA' can only be used as a generic constraint because it has Self or associated type requirements}} } // SR-547 @@ -124,3 +124,5 @@ protocol B { func observeChangeOfProperty(_ property: BC, observable: BA) } + + diff --git a/test/decl/protocol/req/dynamic_self.swift b/test/decl/protocol/req/dynamic_self.swift index 758a301ef6f22..ef4f33a100b1d 100644 --- a/test/decl/protocol/req/dynamic_self.swift +++ b/test/decl/protocol/req/dynamic_self.swift @@ -86,3 +86,39 @@ enum EError : P { // expected-error{{type 'EError' does not conform to protocol subscript() -> Int { 0 } // expected-note{{candidate has non-matching type '() -> Int'}} func f() -> Int { 0 } // expected-note{{candidate has non-matching type '() -> Int'}} } + + +// Settable storage declaration requirements with a 'Self' result type may not +// be used with an existential base. +protocol P2 { + subscript() -> Self { get set } +} +protocol P3 { + var prop: Self { get set } +} +protocol P4 { + subscript() -> T where T.Element == Self { get set } +} +func takesP2P3P4(p2: P2, p3: P3, p4: P4) { } +// expected-error@-1{{protocol 'P2' can only be used as a generic constraint because it has Self or associated type requirements}} +// expected-error@-2{{protocol 'P3' can only be used as a generic constraint because it has Self or associated type requirements}} + +protocol P5 { +} +extension P5 { + var prop: Self { + get { self } + set { } + } + + subscript() -> Self { + get { self } + set { } + } +} +func takesP5(p5: P5) { + _ = p5[] + // expected-error@-1{{member 'subscript' cannot be used on value of protocol type 'P5'; use a generic constraint instead}} + _ = p5.prop + // expected-error@-1{{member 'prop' cannot be used on value of protocol type 'P5'; use a generic constraint instead}} +} diff --git a/test/stmt/foreach.swift b/test/stmt/foreach.swift index e3c3d6a3cb6eb..20ddf6add1cfd 100644 --- a/test/stmt/foreach.swift +++ b/test/stmt/foreach.swift @@ -175,8 +175,8 @@ func testOptionalSequence() { } } -// FIXME: Should this be allowed? -func testExistentialSequence(s: Sequence) { +// Crash with (invalid) for each over an existential +func testExistentialSequence(s: Sequence) { // expected-error {{protocol 'Sequence' can only be used as a generic constraint because it has Self or associated type requirements}} for x in s { // expected-error {{protocol 'Sequence' as a type cannot conform to the protocol itself}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}} _ = x } diff --git a/test/type/protocol_types.swift b/test/type/protocol_types.swift index 84c98f6daeccd..840dd52b3a311 100644 --- a/test/type/protocol_types.swift +++ b/test/type/protocol_types.swift @@ -3,7 +3,7 @@ protocol HasSelfRequirements { func foo(_ x: Self) - func returnsOwnProtocol() -> HasSelfRequirements + func returnsOwnProtocol() -> HasSelfRequirements // expected-error{{protocol 'HasSelfRequirements' can only be used as a generic constraint because it has Self or associated type requirements}} {{educational-notes=associated-type-requirements}} } protocol Bar { // init() methods should not prevent use as an existential. @@ -36,11 +36,10 @@ func useCompoAsWhereRequirement(_ x: T) where T: HasSelfRequirements & Bar {} func useCompoAliasAsWhereRequirement(_ x: T) where T: Compo {} func useNestedCompoAliasAsWhereRequirement(_ x: T) where T: CompoAssocType.Compo {} -func useAsType(_: HasSelfRequirements, - _: HasSelfRequirements & Bar, - _: Compo, - _: CompoAssocType.Compo) { } -func useCompoAsType(_ x: HasSelfRequirements & Bar) { } +func useAsType(_ x: HasSelfRequirements) { } // expected-error{{protocol 'HasSelfRequirements' can only be used as a generic constraint}} +func useCompoAsType(_ x: HasSelfRequirements & Bar) { } // expected-error{{protocol 'HasSelfRequirements' can only be used as a generic constraint}} +func useCompoAliasAsType(_ x: Compo) { } // expected-error{{protocol 'HasSelfRequirements' can only be used as a generic constraint}} +func useNestedCompoAliasAsType(_ x: CompoAssocType.Compo) { } // expected-error{{protocol 'HasSelfRequirements' can only be used as a generic constraint}} struct TypeRequirement {} struct CompoTypeRequirement {} @@ -68,43 +67,29 @@ protocol HasAssoc { func foo() } -do { - enum MyError : Error { - case bad(Any) - } - - func checkIt(_ js: Any) throws { - switch js { - case let dbl as HasAssoc: - throw MyError.bad(dbl) - - default: - fatalError("wrong") - } - } -} - -func testHasAssoc(_ x: Any, _: HasAssoc) { - if let p = x as? HasAssoc { +func testHasAssoc(_ x: Any) { + if let p = x as? HasAssoc { // expected-error {{protocol 'HasAssoc' can only be used as a generic constraint}} {{educational-notes=associated-type-requirements}} p.foo() // don't crash here. } +} - struct ConformingType : HasAssoc { - typealias Assoc = Int - func foo() {} +// rdar://problem/16803384 +protocol InheritsAssoc : HasAssoc { + func silverSpoon() +} - func method() -> HasAssoc {} - } +func testInheritsAssoc(_ x: InheritsAssoc) { // expected-error {{protocol 'InheritsAssoc' can only be used as a generic constraint}} + x.silverSpoon() } // SR-38 -var b: HasAssoc +var b: HasAssoc // expected-error {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} // Further generic constraint error testing - typealias used inside statements protocol P {} typealias MoreHasAssoc = HasAssoc & P func testHasMoreAssoc(_ x: Any) { - if let p = x as? MoreHasAssoc { + if let p = x as? MoreHasAssoc { // expected-error {{protocol 'HasAssoc' can only be used as a generic constraint}} p.foo() // don't crash here. } } @@ -118,30 +103,37 @@ struct Outer { typealias X = Struct1 _ = Struct1.self -typealias AliasWhere = T +typealias BadAlias = T where T : HasAssoc, T.Assoc == HasAssoc +// expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} -struct StructWhere +struct BadStruct where T : HasAssoc, T.Assoc == HasAssoc {} +// expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} -protocol ProtocolWhere where T == HasAssoc { +protocol BadProtocol where T == HasAssoc { + // expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} associatedtype T associatedtype U : HasAssoc where U.Assoc == HasAssoc + // expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} } extension HasAssoc where Assoc == HasAssoc {} +// expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} -func FunctionWhere(_: T) +func badFunction(_: T) where T : HasAssoc, T.Assoc == HasAssoc {} +// expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} -struct SubscriptWhere { +struct BadSubscript { subscript(_: T) -> Int where T : HasAssoc, T.Assoc == HasAssoc { + // expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} get {} set {} } @@ -149,4 +141,5 @@ struct SubscriptWhere { struct OuterGeneric { func contextuallyGenericMethod() where T == HasAssoc {} + // expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} } diff --git a/userdocs/diagnostics/associated-type-requirements.md b/userdocs/diagnostics/associated-type-requirements.md new file mode 100644 index 0000000000000..47c5dda89ee47 --- /dev/null +++ b/userdocs/diagnostics/associated-type-requirements.md @@ -0,0 +1,28 @@ +# Using Protocols with `Self` or Associated Type Requirements + +Protocols in Swift may be used as types, as part of a generic constraint, or as part of an opaque result type. + +```swift +// `CustomStringConvertible` can be used as a type. +func foo(bar: CustomStringConvertible) { /* ... */ } + +// ...or as a generic constraint on `T`. +func bar(baz: T) { /* ... */ } + +// ...or as part of an opaque result type. +func baz() -> some CustomStringConvertible { /* ... */ } +``` + +While all Swift protocols can be used as generic constraints and as part of opaque result types, not all protocols can be used as types. Specifically, if a protocol has a requirement which references `Self` (in contexts other than a function's return type) or an associated type, it cannot be used as a type. For example, the protocol `Equatable` requires `static func == (lhs: Self, rhs: Self) -> Bool`, and the protocol `Identifiable` requires `var id: ID { get }`, where `ID` is an associated type. As a result, the following code is not allowed: + +```swift +func foo(bar: Equatable) { /* ... */ } +// error: protocol 'Equatable' can only be used as a generic constraint because it has Self or associated type requirements + +func foo(bar: Identifiable) { /* ... */ } +// error: protocol 'Identifiable' can only be used as a generic constraint because it has Self or associated type requirements +``` + +These `Self` or associated type requirements cannot be used via a protocol type because they do not have a well-defined meaning without a concrete conforming type. Therefore, Swift does not support the use of protocols as types if they have such `Self` or associated type requirements, since those types would be able to present only a potentially unusable subset of the interface required for instances of concrete conforming types. + +When working with protocols that have `Self` or associated type requirements, most use cases can be supported by constrained generics, opaque result types, or manual type erasure. To learn more, see the sections on [protocols](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html), [generics](https://docs.swift.org/swift-book/LanguageGuide/Generics.html), and [opaque types](https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html) in _The Swift Programming Language_. diff --git a/userdocs/diagnostics/existential-member-access-limitations.md b/userdocs/diagnostics/existential-member-access-limitations.md deleted file mode 100644 index 36776f9172b82..0000000000000 --- a/userdocs/diagnostics/existential-member-access-limitations.md +++ /dev/null @@ -1,54 +0,0 @@ -# Using Protocol Members with References to `Self` or `Self`-rooted Associated Types - -A protocol may be interfaced with via a conformance constraint on a generic parameter, an opaque result type, or via the protocol type itself: - -```swift -// An appropriately constrained generic parameter. -func foo(arg: T) { - let description: String = arg.description -} - -do { - // An appropriately constrained opaque result type. - func foo() -> some CustomStringConvertible { true } - - let description: String = foo().description -} - -// The protocol type. -func foo(arg: CustomStringConvertible) { - let description: String = arg.description -} -``` - -While the former two options enable full access to the protocol interface, not all members may be accessible when the protocol is used as a type and not a constraint. Specifically, a protocol member cannot be accessed on a protocol type when its type signature contains a reference to `Self` or a `Self`-rooted associated type. Accessing such members on a protocol type is not supported because today the compiler does not have a well-defined meaning and means of representation for `Self` and `Self`-rooted associated types with respect to a protocol type `P`. As a result, the following code is not allowed: - -```swift -protocol Shape { - func matches(_ other: Self) -> Bool -} - -func foo(_ shape: Shape) { - // error: member 'matches' cannot be used on value of protocol type 'Shape'; use a generic constraint instead - shape.matches(shape) -} - -func foo(_ arg: Identifiable) { - // error: member 'id' cannot be used on value of protocol type 'Identifiable'; use a generic constraint instead - _ = arg.id -} -``` - -An expection to this limitation are members that contain `Self` only in [covariant](https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)) position (such as a method result type), where `Self` can be safely substituted with the protocol or protocol composition type used to access the member — a representable supertype. On the other hand, resorting to this ploy in contravariant parameter type position, like allowing one to pass a type-erased value to a method that accepts `Self`, is not type-safe and would expose the opportunity to pass in an argument of non-matching type. - -```swift -protocol Shape { - func duplicate() -> Self -} - -func duplicateShape(_ shape: Shape) -> Shape { - return shape.duplicate // OK, produces a value of type 'Shape' -} -``` - -Most use cases involving usage of protocol members that fall under the above restriction can instead be supported by constrained generics, opaque result types, or manual type-erasing wrappers. To learn more, see the sections on [protocols](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html), [generics](https://docs.swift.org/swift-book/LanguageGuide/Generics.html), and [opaque types](https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html) in the Language Guide. For a better understanding of existential types in particular, and an in-depth exploration of the relationships among these built-in abstraction models, we recommend reading the [design document for improving the UI of the generics model](https://forums.swift.org/t/improving-the-ui-of-generics/22814).