diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index cf462c4811cc8..4c304b7ea1cf9 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -514,7 +514,7 @@ class alignas(1 << DeclAlignInBits) Decl { IsComputingSemanticMembers : 1 ); - SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+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+8+16, /// Whether the \c RequiresClass bit is valid. RequiresClassValid : 1, @@ -527,12 +527,6 @@ class alignas(1 << DeclAlignInBits) Decl { /// 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, @@ -4157,21 +4151,6 @@ 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; } @@ -4181,7 +4160,6 @@ class ProtocolDecl final : public NominalTypeDecl { friend class RequirementSignatureRequest; friend class ProtocolRequiresClassRequest; friend class ExistentialConformsToSelfRequest; - friend class ExistentialTypeSupportedRequest; friend class InheritedProtocolsRequest; public: @@ -4270,12 +4248,6 @@ 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 4af092ddb775b..783d2f5168025 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -920,9 +920,6 @@ 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 0ba9c1e9fdd13..bc57ec20410c0 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(unsupported_existential_type, - "associated-type-requirements.md") +EDUCATIONAL_NOTES(could_not_use_member_on_existential, + "existential-member-access-limitations.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 d5ba12351e716..7c28cd38b2290 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -287,32 +287,6 @@ 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); } - // Most bound generic types are invariant. - if (auto *const bgt = type->getAs()) { + if (auto *const nominal = type->getAs()) { auto info = SelfReferenceInfo(); - 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, + // 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(), SelfReferencePosition::Invariant); + info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().back(), + position); + } else { + for (auto paramType : bgt->getGenericArgs()) { + info |= findProtocolSelfReferences(proto, paramType, + SelfReferencePosition::Invariant); + } } } @@ -5049,6 +5056,16 @@ 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); @@ -5148,11 +5165,6 @@ 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 0f39a6748c437..13e64e9ae0b25 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -253,31 +253,6 @@ 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 defc94195420c..340267968414d 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -7302,7 +7302,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(); - auto baseObjTy = baseTy->getRValueType(); + const auto baseObjTy = baseTy->getRValueType(); bool hasInstanceMembers = false; bool hasInstanceMethods = false; @@ -7349,18 +7349,6 @@ 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. @@ -7380,6 +7368,20 @@ 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. @@ -7393,20 +7395,35 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, ? candidate : OverloadChoice(instanceTy, decl, FunctionRefKind::SingleApply); - // 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) + + 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); 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 @@ -7457,6 +7474,12 @@ 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 b66f7b88605bc..46292cc667b5a 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -3342,8 +3342,6 @@ 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. @@ -4760,8 +4758,6 @@ 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 3607837b236a5..4755c7faceeac 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -672,34 +672,6 @@ 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 35b646516e46b..67b18808e70c6 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1659,8 +1659,6 @@ 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 a6cb966d0a1f8..e67d0a3d0541e 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -4015,159 +4015,6 @@ 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 a0849aaa95be4..7348bee93b389 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -242,22 +242,6 @@ 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 1c4aab3483a5a..3dff7b9d2fda8 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -3561,14 +3561,13 @@ class DeclDeserializer { StringRef blobData) { IdentifierID nameID; DeclContextID contextID; - bool isImplicit, isClassBounded, isObjC, existentialTypeSupported; + bool isImplicit, isClassBounded, isObjC; uint8_t rawAccessLevel; unsigned numInheritedTypes; ArrayRef rawInheritedAndDependencyIDs; decls_block::ProtocolLayout::readRecord(scratch, nameID, contextID, isImplicit, isClassBounded, isObjC, - existentialTypeSupported, rawAccessLevel, numInheritedTypes, rawInheritedAndDependencyIDs); @@ -3594,8 +3593,6 @@ 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 f35c9d2d8f483..97c360c9dd90a 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -1252,7 +1252,6 @@ 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 8f2bf60f4ff2a..a127918e66152 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -3537,7 +3537,6 @@ 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 d9f342729509a..0516e08d92dc4 100644 --- a/test/Constraints/static_members_on_protocol_in_generic_context.swift +++ b/test/Constraints/static_members_on_protocol_in_generic_context.swift @@ -265,24 +265,6 @@ 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 5b83dba7d8c0c..8b5d8499ebfa3 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 // expected-error{{protocol 'EqualComparable' can only be used as a generic constraint}} + var eqComp : EqualComparable = t1 // Ok 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,20 +49,11 @@ func otherExistential(_ t1: T) { otherEqComp = t1 // expected-error{{value of type 'T' does not conform to 'OtherEqualComparable' in assignment}} _ = otherEqComp - var otherEqComp2 : OtherEqualComparable // expected-error{{protocol 'OtherEqualComparable' can only be used as a generic constraint}} + var otherEqComp2 : OtherEqualComparable // Ok 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}} 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) + _ = t1 as EqualComparable & OtherEqualComparable // expected-error{{value of type 'T' does not conform to 'EqualComparable & OtherEqualComparable' in coercion}} } //===----------------------------------------------------------------------===// diff --git a/test/Sema/existential_nested_type.swift b/test/Sema/existential_nested_type.swift deleted file mode 100644 index 8189415c1f70e..0000000000000 --- a/test/Sema/existential_nested_type.swift +++ /dev/null @@ -1,24 +0,0 @@ -// 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 2ccc15b74e9a3..ab0427513619a 100644 --- a/test/decl/nested/protocol.swift +++ b/test/decl/nested/protocol.swift @@ -31,8 +31,7 @@ protocol OuterProtocol { struct ConformsToOuterProtocol : OuterProtocol { typealias Hen = Int - 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}} + func f() { let _ = InnerProtocol.self } // Ok } protocol Racoon { diff --git a/test/decl/nested/type_in_function.swift b/test/decl/nested/type_in_function.swift index 7fa1c325d4b60..3908dad939434 100644 --- a/test/decl/nested/type_in_function.swift +++ b/test/decl/nested/type_in_function.swift @@ -135,20 +135,6 @@ 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 75c4c5de1aa21..33e50e5ee418b 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 // expected-error{{has Self or associated type requirements}} - var _: P4 = b // expected-error{{has Self or associated type requirements}} + var _: P1 = b + var _: P4 = b var _: P5 = b var _: P6 = 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}} + var _: P7 = b + var _: P8 = b + var _: P9 = b } // Class A5 conforms to P5 in an inheritable manner. diff --git a/test/decl/protocol/protocols.swift b/test/decl/protocol/protocols.swift index 0a2d9c5e48b39..6689695102b62 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 2 {{protocol 'CircleMiddle' declared here}} -protocol CircleStart : CircleEnd { func circle_start() } // expected-error 2 {{protocol 'CircleStart' refines itself}} +// expected-note@-1 {{protocol 'CircleMiddle' declared here}} +protocol CircleStart : CircleEnd { func circle_start() } // expected-error {{protocol 'CircleStart' refines itself}} // expected-note@-1 {{protocol 'CircleStart' declared here}} -protocol CircleEnd : CircleMiddle { func circle_end()} // expected-note 3 {{protocol 'CircleEnd' declared here}} +protocol CircleEnd : CircleMiddle { func circle_end()} // expected-note 2 {{protocol 'CircleEnd' declared here}} protocol CircleEntry : CircleTrivial { } protocol CircleTrivial : CircleTrivial { } // expected-error {{protocol 'CircleTrivial' refines itself}} @@ -263,55 +263,6 @@ 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 //===----------------------------------------------------------------------===// @@ -488,18 +439,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 // expected-error{{protocol 'P1' can only be used as a generic constraint because it has Self or associated type requirements}} + _ = x as P1 } func i(_ x : T?) -> Bool { - return x is P1 // expected-error{{protocol 'P1' can only be used as a generic constraint because it has Self or associated type requirements}} + return x is P1 // 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 // expected-error{{protocol 'P1' can only be used as a generic constraint because it has Self or associated type requirements}} + return x is P1 } func k(_ x : C1?) -> Bool { - return x is P1 // expected-error{{protocol 'P1' can only be used as a generic constraint because it has Self or associated type requirements}} + return x is P1 } diff --git a/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift new file mode 100644 index 0000000000000..a82f86b0d3aa9 --- /dev/null +++ b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift @@ -0,0 +1,523 @@ +// 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 new file mode 100644 index 0000000000000..58aa147a3ebe9 --- /dev/null +++ b/test/decl/protocol/protocols_with_self_or_assoc_reqs_executable.swift @@ -0,0 +1,107 @@ +// 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 fd6ee93d412ae..c99dadbb6b4bd 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 } // expected-error {{protocol 'AsExistentialAssocTypeB' can only be used as a generic constraint because it has Self or associated type requirements}} + var delegate : AsExistentialAssocTypeB? { get } } protocol AsExistentialAssocTypeB { func aMethod(_ object : AsExistentialAssocTypeA) @@ -103,7 +103,7 @@ protocol AsExistentialAssocTypeAgainA { associatedtype Bar } protocol AsExistentialAssocTypeAgainB { - func aMethod(_ object : AsExistentialAssocTypeAgainA) // expected-error {{protocol 'AsExistentialAssocTypeAgainA' can only be used as a generic constraint because it has Self or associated type requirements}} + func aMethod(_ object : AsExistentialAssocTypeAgainA) } // SR-547 @@ -124,5 +124,3 @@ 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 ef4f33a100b1d..758a301ef6f22 100644 --- a/test/decl/protocol/req/dynamic_self.swift +++ b/test/decl/protocol/req/dynamic_self.swift @@ -86,39 +86,3 @@ 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 20ddf6add1cfd..e3c3d6a3cb6eb 100644 --- a/test/stmt/foreach.swift +++ b/test/stmt/foreach.swift @@ -175,8 +175,8 @@ func testOptionalSequence() { } } -// 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}} +// FIXME: Should this be allowed? +func testExistentialSequence(s: Sequence) { 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 840dd52b3a311..84c98f6daeccd 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 // 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}} + func returnsOwnProtocol() -> HasSelfRequirements } protocol Bar { // init() methods should not prevent use as an existential. @@ -36,10 +36,11 @@ 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(_ 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}} +func useAsType(_: HasSelfRequirements, + _: HasSelfRequirements & Bar, + _: Compo, + _: CompoAssocType.Compo) { } +func useCompoAsType(_ x: HasSelfRequirements & Bar) { } struct TypeRequirement {} struct CompoTypeRequirement {} @@ -67,29 +68,43 @@ protocol HasAssoc { func foo() } -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. +do { + enum MyError : Error { + case bad(Any) } -} -// rdar://problem/16803384 -protocol InheritsAssoc : HasAssoc { - func silverSpoon() + func checkIt(_ js: Any) throws { + switch js { + case let dbl as HasAssoc: + throw MyError.bad(dbl) + + default: + fatalError("wrong") + } + } } -func testInheritsAssoc(_ x: InheritsAssoc) { // expected-error {{protocol 'InheritsAssoc' can only be used as a generic constraint}} - x.silverSpoon() +func testHasAssoc(_ x: Any, _: HasAssoc) { + if let p = x as? HasAssoc { + p.foo() // don't crash here. + } + + struct ConformingType : HasAssoc { + typealias Assoc = Int + func foo() {} + + func method() -> HasAssoc {} + } } // SR-38 -var b: HasAssoc // expected-error {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} +var b: HasAssoc // 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 { // expected-error {{protocol 'HasAssoc' can only be used as a generic constraint}} + if let p = x as? MoreHasAssoc { p.foo() // don't crash here. } } @@ -103,37 +118,30 @@ struct Outer { typealias X = Struct1 _ = Struct1.self -typealias BadAlias = T +typealias AliasWhere = 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 BadStruct +struct StructWhere 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 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}} +protocol ProtocolWhere where T == HasAssoc { 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 badFunction(_: T) +func FunctionWhere(_: 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 BadSubscript { +struct SubscriptWhere { 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 {} } @@ -141,5 +149,4 @@ struct BadSubscript { 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 deleted file mode 100644 index 47c5dda89ee47..0000000000000 --- a/userdocs/diagnostics/associated-type-requirements.md +++ /dev/null @@ -1,28 +0,0 @@ -# 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 new file mode 100644 index 0000000000000..36776f9172b82 --- /dev/null +++ b/userdocs/diagnostics/existential-member-access-limitations.md @@ -0,0 +1,54 @@ +# 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).