diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index f57f390143a12..bb83a245859b1 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -531,7 +531,7 @@ class ASTContext final { /// Retrieve the declaration of Swift.Error. ProtocolDecl *getErrorDecl() const; - CanType getExceptionType() const; + CanType getErrorExistentialType() const; #define KNOWN_STDLIB_TYPE_DECL(NAME, DECL_CLASS, NUM_GENERIC_PARAMS) \ /** Retrieve the declaration of Swift.NAME. */ \ diff --git a/include/swift/AST/ASTDemangler.h b/include/swift/AST/ASTDemangler.h index 76c90f017c9a5..8e4100d77396e 100644 --- a/include/swift/AST/ASTDemangler.h +++ b/include/swift/AST/ASTDemangler.h @@ -66,7 +66,7 @@ class ASTBuilder { Demangle::NodeFactory &getNodeFactory() { return Factory; } - Type decodeMangledType(NodePointer node); + Type decodeMangledType(NodePointer node, bool forRequirement = true); Type createBuiltinType(StringRef builtinName, StringRef mangledName); TypeDecl *createTypeDecl(NodePointer node); @@ -109,7 +109,8 @@ class ASTBuilder { Type createProtocolCompositionType(ArrayRef<ProtocolDecl *> protocols, Type superclass, - bool isClassBound); + bool isClassBound, + bool forRequirement = true); Type createExistentialMetatypeType(Type instance, Optional<Demangle::ImplMetatypeRepresentation> repr=None); diff --git a/include/swift/AST/ASTSynthesis.h b/include/swift/AST/ASTSynthesis.h index 7ea55cf8c028f..6437e6a1cee5b 100644 --- a/include/swift/AST/ASTSynthesis.h +++ b/include/swift/AST/ASTSynthesis.h @@ -56,7 +56,7 @@ inline Type synthesizeType(SynthesisContext &SC, switch (kind) { case _any: return SC.Context.TheAnyType; case _bridgeObject: return SC.Context.TheBridgeObjectType; - case _error: return SC.Context.getExceptionType(); + case _error: return SC.Context.getErrorExistentialType(); case _executor: return SC.Context.TheExecutorType; case _job: return SC.Context.TheJobType; case _nativeObject: return SC.Context.TheNativeObjectType; diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index ff6fe4e2225b5..8ca2157cda0d3 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -4363,6 +4363,11 @@ class ProtocolDecl final : public NominalTypeDecl { /// not exist. AssociatedTypeDecl *getAssociatedType(Identifier name) const; + /// Returns the existential type for this protocol. + Type getExistentialType() const { + return ExistentialType::get(getDeclaredInterfaceType()); + } + /// Walk this protocol and all of the protocols inherited by this protocol, /// transitively, invoking the callback function for each protocol. /// diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 63dbe7f1ea7d8..4987a8a41fa7f 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -2441,8 +2441,8 @@ ERROR(protocol_composition_one_class,none, "contains class %1", (Type, Type)) ERROR(requires_conformance_nonprotocol,none, - "type %0 constrained to non-protocol, non-class type %1", - (Type, Type)) + "type %0 constrained to non-protocol, non-class type '%1'", + (Type, StringRef)) NOTE(requires_conformance_nonprotocol_fixit,none, "use '%0 == %1' to require '%0' to be '%1'", (StringRef, StringRef)) @@ -4648,8 +4648,6 @@ ERROR(unchecked_not_inheritance_clause,none, ERROR(unchecked_not_existential,none, "'unchecked' attribute cannot apply to non-protocol type %0", (Type)) -WARNING(unnecessary_any,none, - "'any' is redundant on type %0", (Type)) ERROR(any_not_existential,none, "'any' has no effect on %select{concrete type|type parameter}0 %1", (bool, Type)) diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h index 78499df4b11ce..8a7a8787b2da3 100644 --- a/include/swift/AST/PrintOptions.h +++ b/include/swift/AST/PrintOptions.h @@ -278,6 +278,10 @@ struct PrintOptions { bool PrintImplicitAttrs = true; + /// Whether to print the \c any keyword for existential + /// types. + bool PrintExplicitAny = false; + /// Whether to skip keywords with a prefix of underscore such as __consuming. bool SkipUnderscoredKeywords = false; diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h index d84459e1e7904..714349cfdcb18 100644 --- a/include/swift/AST/ProtocolConformance.h +++ b/include/swift/AST/ProtocolConformance.h @@ -660,7 +660,7 @@ class SelfProtocolConformance : public RootProtocolConformance { public: /// Get the protocol being conformed to. ProtocolDecl *getProtocol() const { - return getType()->castTo<ProtocolType>()->getDecl(); + return dyn_cast<ProtocolDecl>(getType()->getAnyNominal()); } /// Get the declaration context in which this conformance was declared. diff --git a/include/swift/AST/Type.h b/include/swift/AST/Type.h index 467753c4df00d..3b7650a430338 100644 --- a/include/swift/AST/Type.h +++ b/include/swift/AST/Type.h @@ -385,6 +385,7 @@ class CanType : public Type { static bool isReferenceTypeImpl(CanType type, const GenericSignatureImpl *sig, bool functionsCount); + static bool isConstraintTypeImpl(CanType type); static bool isExistentialTypeImpl(CanType type); static bool isAnyExistentialTypeImpl(CanType type); static bool isObjCExistentialTypeImpl(CanType type); @@ -457,6 +458,10 @@ class CanType : public Type { /*functions count*/ false); } + bool isConstraintType() const { + return isConstraintTypeImpl(*this); + } + /// Is this type existential? bool isExistentialType() const { return isExistentialTypeImpl(*this); diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index c1fa303a8f44f..a848f1dbcff48 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -727,6 +727,9 @@ class alignas(1 << TypeAlignInBits) TypeBase return getRecursiveProperties().hasDependentMember(); } + /// Whether this type represents a generic constraint. + bool isConstraintType() const; + /// isExistentialType - Determines whether this type is an existential type, /// whose real (runtime) type is unknown but which is known to conform to /// some set of protocols. Protocol and protocol-conformance types are @@ -2731,6 +2734,8 @@ class ExistentialMetatypeType : public AnyMetatypeType { static bool classof(const TypeBase *T) { return T->getKind() == TypeKind::ExistentialMetatype; } + + Type getExistentialInstanceType(); private: ExistentialMetatypeType(Type T, const ASTContext *C, @@ -5243,7 +5248,7 @@ class ExistentialType final : public TypeBase { ConstraintType(constraintType) {} public: - static ExistentialType *get(Type constraint); + static Type get(Type constraint); Type getConstraintType() const { return ConstraintType; } @@ -6335,6 +6340,15 @@ inline GenericTypeParamType *TypeBase::getRootGenericParam() { return t->castTo<GenericTypeParamType>(); } +inline bool TypeBase::isConstraintType() const { + return getCanonicalType().isConstraintType(); +} + +inline bool CanType::isConstraintTypeImpl(CanType type) { + return (isa<ProtocolType>(type) || + isa<ProtocolCompositionType>(type)); +} + inline bool TypeBase::isExistentialType() { return getCanonicalType().isExistentialType(); } @@ -6441,6 +6455,8 @@ inline NominalTypeDecl *TypeBase::getNominalOrBoundGenericNominal() { inline NominalTypeDecl *CanType::getNominalOrBoundGenericNominal() const { if (auto Ty = dyn_cast<NominalOrBoundGenericNominalType>(*this)) return Ty->getDecl(); + if (auto Ty = dyn_cast<ExistentialType>(*this)) + return Ty->getConstraintType()->getNominalOrBoundGenericNominal(); return nullptr; } @@ -6449,6 +6465,9 @@ inline NominalTypeDecl *TypeBase::getAnyNominal() { } inline Type TypeBase::getNominalParent() { + if (auto existential = getAs<ExistentialType>()) + return existential->getConstraintType()->getNominalParent(); + return castTo<AnyGenericType>()->getParent(); } diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index 1bfed64e7d81e..3960c4d73e7f0 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -315,7 +315,7 @@ namespace swift { /// Enable support for explicit existential types via the \c any /// keyword. - bool EnableExplicitExistentialTypes = false; + bool EnableExplicitExistentialTypes = true; /// Enable experimental flow-sensitive concurrent captures. bool EnableExperimentalFlowSensitiveConcurrentCaptures = false; diff --git a/include/swift/Demangling/TypeDecoder.h b/include/swift/Demangling/TypeDecoder.h index 73a86f320d77c..07b5e5161dc70 100644 --- a/include/swift/Demangling/TypeDecoder.h +++ b/include/swift/Demangling/TypeDecoder.h @@ -372,12 +372,16 @@ void decodeRequirement(NodePointer node, BuiltType constraintType; if (child->getKind() == - Demangle::Node::Kind::DependentGenericConformanceRequirement || - child->getKind() == - Demangle::Node::Kind::DependentGenericSameTypeRequirement) { + Demangle::Node::Kind::DependentGenericConformanceRequirement) { constraintType = Builder.decodeMangledType(child->getChild(1)); if (!constraintType) return; + } else if (child->getKind() == + Demangle::Node::Kind::DependentGenericSameTypeRequirement) { + constraintType = Builder.decodeMangledType( + child->getChild(1), /*forRequirement=*/false); + if (!constraintType) + return; } switch (child->getKind()) { @@ -468,15 +472,17 @@ class TypeDecoder { explicit TypeDecoder(BuilderType &Builder) : Builder(Builder) {} /// Given a demangle tree, attempt to turn it into a type. - TypeLookupErrorOr<BuiltType> decodeMangledType(NodePointer Node) { - return decodeMangledType(Node, 0); + TypeLookupErrorOr<BuiltType> decodeMangledType(NodePointer Node, + bool forRequirement = true) { + return decodeMangledType(Node, 0, forRequirement); } protected: static const unsigned MaxDepth = 1024; TypeLookupErrorOr<BuiltType> decodeMangledType(NodePointer Node, - unsigned depth) { + unsigned depth, + bool forRequirement = true) { if (depth > TypeDecoder::MaxDepth) return TypeLookupError("Mangled type is too complex"); @@ -499,7 +505,8 @@ class TypeDecoder { if (Node->getNumChildren() < 1) return MAKE_NODE_TYPE_ERROR0(Node, "no children."); - return decodeMangledType(Node->getChild(0), depth + 1); + return decodeMangledType(Node->getChild(0), depth + 1, + forRequirement); case NodeKind::Class: { #if SWIFT_OBJC_INTEROP @@ -543,7 +550,8 @@ class TypeDecoder { return MAKE_NODE_TYPE_ERROR0(genericArgs, "is not TypeList"); for (auto genericArg : *genericArgs) { - auto paramType = decodeMangledType(genericArg, depth + 1); + auto paramType = decodeMangledType(genericArg, depth + 1, + /*forRequirement=*/false); if (paramType.isError()) return paramType; args.push_back(paramType.getType()); @@ -698,14 +706,16 @@ class TypeDecoder { } return Builder.createProtocolCompositionType(Protocols, Superclass, - IsClassBound); + IsClassBound, + forRequirement); } case NodeKind::Protocol: case NodeKind::ProtocolSymbolicReference: { if (auto Proto = decodeMangledProtocolType(Node, depth + 1)) { return Builder.createProtocolCompositionType(Proto, BuiltType(), - /*IsClassBound=*/false); + /*IsClassBound=*/false, + forRequirement); } return MAKE_NODE_TYPE_ERROR0(Node, "failed to decode protocol type"); @@ -845,7 +855,8 @@ class TypeDecoder { Node->getKind() == NodeKind::EscapingObjCBlock); auto result = - decodeMangledType(Node->getChild(firstChildIdx + 1), depth + 1); + decodeMangledType(Node->getChild(firstChildIdx + 1), depth + 1, + /*forRequirement=*/false); if (result.isError()) return result; return Builder.createFunctionType( @@ -962,7 +973,8 @@ class TypeDecoder { if (Node->getNumChildren() < 1) return MAKE_NODE_TYPE_ERROR0(Node, "no children"); - return decodeMangledType(Node->getChild(0), depth + 1); + return decodeMangledType(Node->getChild(0), depth + 1, + /*forRequirement=*/false); case NodeKind::Tuple: { llvm::SmallVector<BuiltType, 8> elements; @@ -994,7 +1006,8 @@ class TypeDecoder { // Decode the element type. auto elementType = - decodeMangledType(element->getChild(typeChildIndex), depth + 1); + decodeMangledType(element->getChild(typeChildIndex), depth + 1, + /*forRequirement=*/false); if (elementType.isError()) return elementType; @@ -1012,9 +1025,11 @@ class TypeDecoder { "fewer children (%zu) than required (2)", Node->getNumChildren()); - return decodeMangledType(Node->getChild(1), depth + 1); + return decodeMangledType(Node->getChild(1), depth + 1, + /*forRequirement=*/false); } - return decodeMangledType(Node->getChild(0), depth + 1); + return decodeMangledType(Node->getChild(0), depth + 1, + /*forRequirement=*/false); case NodeKind::DependentGenericType: { if (Node->getNumChildren() < 2) @@ -1161,7 +1176,8 @@ return {}; // Not Implemented! "more substitutions than generic params"); while (index >= genericParamsAtDepth[paramDepth]) ++paramDepth, index = 0; - auto substTy = decodeMangledType(subst, depth + 1); + auto substTy = decodeMangledType(subst, depth + 1, + /*forRequirement=*/false); if (substTy.isError()) return substTy; substitutions.emplace_back( @@ -1243,7 +1259,8 @@ return {}; // Not Implemented! if (genericsNode->getKind() != NodeKind::TypeList) break; for (auto argNode : *genericsNode) { - auto arg = decodeMangledType(argNode, depth + 1); + auto arg = decodeMangledType(argNode, depth + 1, + /*forRequirement=*/false); if (arg.isError()) return arg; genericArgsBuf.push_back(arg.getType()); @@ -1480,7 +1497,8 @@ return {}; // Not Implemented! } } - auto paramType = decodeMangledType(node, depth + 1); + auto paramType = decodeMangledType(node, depth + 1, + /*forRequirement=*/false); if (paramType.isError()) return false; @@ -1544,8 +1562,10 @@ return {}; // Not Implemented! template <typename BuilderType> inline TypeLookupErrorOr<typename BuilderType::BuiltType> -decodeMangledType(BuilderType &Builder, NodePointer Node) { - return TypeDecoder<BuilderType>(Builder).decodeMangledType(Node); +decodeMangledType(BuilderType &Builder, NodePointer Node, + bool forRequirement = false) { + return TypeDecoder<BuilderType>(Builder) + .decodeMangledType(Node, forRequirement); } SWIFT_END_INLINE_NAMESPACE diff --git a/include/swift/Reflection/TypeRefBuilder.h b/include/swift/Reflection/TypeRefBuilder.h index 913508ce5a03d..8732961f7cc30 100644 --- a/include/swift/Reflection/TypeRefBuilder.h +++ b/include/swift/Reflection/TypeRefBuilder.h @@ -289,7 +289,7 @@ class TypeRefBuilder { void clearNodeFactory() { Dem.clear(); } - BuiltType decodeMangledType(Node *node); + BuiltType decodeMangledType(Node *node, bool forRequirement = true); /// /// Factory methods for all TypeRef kinds @@ -492,7 +492,8 @@ class TypeRefBuilder { const ProtocolCompositionTypeRef * createProtocolCompositionType(llvm::ArrayRef<BuiltProtocolDecl> protocols, - BuiltType superclass, bool isClassBound) { + BuiltType superclass, bool isClassBound, + bool forRequirement = true) { std::vector<const TypeRef *> protocolRefs; for (const auto &protocol : protocols) { if (!protocol) diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h index 9516c9fc1b76a..29c463576dfd5 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -2220,7 +2220,7 @@ visitOpenExistentialMetatypeInst(OpenExistentialMetatypeInst *Inst) { auto openedType = Inst->getType().getASTType(); auto exType = Inst->getOperand()->getType().getASTType(); while (auto exMetatype = dyn_cast<ExistentialMetatypeType>(exType)) { - exType = exMetatype.getInstanceType(); + exType = exMetatype->getExistentialInstanceType()->getCanonicalType(); openedType = cast<MetatypeType>(openedType).getInstanceType(); } remapOpenedType(cast<OpenedArchetypeType>(openedType)); diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h index d958ceff2ee6b..6e000ffed7904 100644 --- a/include/swift/SIL/SILInstruction.h +++ b/include/swift/SIL/SILInstruction.h @@ -7072,7 +7072,7 @@ class InitExistentialMetatypeInst final auto exType = getType().getASTType(); auto concreteType = getOperand()->getType().getASTType(); while (auto exMetatype = dyn_cast<ExistentialMetatypeType>(exType)) { - exType = exMetatype.getInstanceType(); + exType = exMetatype->getExistentialInstanceType()->getCanonicalType(); concreteType = cast<MetatypeType>(concreteType).getInstanceType(); } assert(exType.isExistentialType()); diff --git a/lib/APIDigester/ModuleAnalyzerNodes.cpp b/lib/APIDigester/ModuleAnalyzerNodes.cpp index e90da097f4313..6d05f5bd1d718 100644 --- a/lib/APIDigester/ModuleAnalyzerNodes.cpp +++ b/lib/APIDigester/ModuleAnalyzerNodes.cpp @@ -1017,6 +1017,12 @@ static StringRef getTypeName(SDKContext &Ctx, Type Ty, if (auto *NAT = dyn_cast<TypeAliasType>(Ty.getPointer())) { return NAT->getDecl()->getNameStr(); } + + if (auto existential = Ty->getAs<ExistentialType>()) { + return getTypeName(Ctx, existential->getConstraintType(), + IsImplicitlyUnwrappedOptional); + } + if (Ty->getAnyNominal()) { if (IsImplicitlyUnwrappedOptional) { assert(Ty->getOptionalObjectType()); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 21bfef2986770..e547554e69b9f 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -847,9 +847,9 @@ Type ASTContext::get##NAME##Type() const { \ } #include "swift/AST/KnownStdlibTypes.def" -CanType ASTContext::getExceptionType() const { +CanType ASTContext::getErrorExistentialType() const { if (auto exn = getErrorDecl()) { - return exn->getDeclaredInterfaceType()->getCanonicalType(); + return exn->getExistentialType()->getCanonicalType(); } else { // Use Builtin.NativeObject just as a stand-in. return TheNativeObjectType; @@ -2256,7 +2256,7 @@ ASTContext::getSelfConformance(ProtocolDecl *protocol) { auto &entry = selfConformances[protocol]; if (!entry) { entry = new (*this, AllocationArena::Permanent) - SelfProtocolConformance(protocol->getDeclaredInterfaceType()); + SelfProtocolConformance(protocol->getExistentialType()); } return entry; } @@ -3319,6 +3319,11 @@ MetatypeType::MetatypeType(Type T, const ASTContext *C, ExistentialMetatypeType * ExistentialMetatypeType::get(Type T, Optional<MetatypeRepresentation> repr, const ASTContext &ctx) { + // If we're creating an existential metatype from an + // existential type, wrap the constraint type direcly. + if (auto existential = T->getAs<ExistentialType>()) + T = existential->getConstraintType(); + auto properties = T->getRecursiveProperties(); auto arena = getArena(properties); @@ -3351,6 +3356,10 @@ ExistentialMetatypeType::ExistentialMetatypeType(Type T, } } +Type ExistentialMetatypeType::getExistentialInstanceType() { + return ExistentialType::get(getInstanceType()); +} + ModuleType *ModuleType::get(ModuleDecl *M) { ASTContext &C = M->getASTContext(); @@ -4103,11 +4112,22 @@ ProtocolType::ProtocolType(ProtocolDecl *TheDecl, Type Parent, RecursiveTypeProperties properties) : NominalType(TypeKind::Protocol, &Ctx, TheDecl, Parent, properties) { } -ExistentialType *ExistentialType::get(Type constraint) { +Type ExistentialType::get(Type constraint) { + auto &C = constraint->getASTContext(); + if (!C.LangOpts.EnableExplicitExistentialTypes) + return constraint; + + // FIXME: Any and AnyObject don't yet use ExistentialType. + if (constraint->isAny() || constraint->isAnyObject()) + return constraint; + + // ExistentialMetatypeType is already an existential type. + if (constraint->is<ExistentialMetatypeType>()) + return constraint; + auto properties = constraint->getRecursiveProperties(); auto arena = getArena(properties); - auto &C = constraint->getASTContext(); auto &entry = C.getImpl().getArena(arena).ExistentialTypes[constraint]; if (entry) return entry; @@ -4316,7 +4336,7 @@ GenericEnvironment *OpenedArchetypeType::getGenericEnvironment() const { CanType OpenedArchetypeType::getAny(Type existential) { if (auto metatypeTy = existential->getAs<ExistentialMetatypeType>()) { - auto instanceTy = metatypeTy->getInstanceType(); + auto instanceTy = metatypeTy->getExistentialInstanceType(); return CanMetatypeType::get(OpenedArchetypeType::getAny(instanceTy)); } assert(existential->isExistentialType()); @@ -4865,7 +4885,7 @@ Type ASTContext::getBridgedToObjC(const DeclContext *dc, Type type, if (auto nsErrorTy = getNSErrorType()) { // The corresponding value type is Error. if (bridgedValueType) - *bridgedValueType = getErrorDecl()->getDeclaredInterfaceType(); + *bridgedValueType = getErrorExistentialType(); return nsErrorTy; } @@ -4902,7 +4922,7 @@ Type ASTContext::getBridgedToObjC(const DeclContext *dc, Type type, if (findConformance(KnownProtocolKind::Error)) { // The corresponding value type is Error. if (bridgedValueType) - *bridgedValueType = getErrorDecl()->getDeclaredInterfaceType(); + *bridgedValueType = getErrorExistentialType(); // Bridge to NSError. if (auto nsErrorTy = getNSErrorType()) @@ -4990,16 +5010,18 @@ CanGenericSignature ASTContext::getSingleGenericParameterSignature() const { // constraints while existential values do. CanGenericSignature ASTContext::getOpenedArchetypeSignature(Type type) { assert(type->isExistentialType()); + if (auto existential = type->getAs<ExistentialType>()) + type = existential->getConstraintType(); - const CanType existential = type->getCanonicalType(); + const CanType constraint = type->getCanonicalType(); // The opened archetype signature for a protocol type is identical // to the protocol's own canonical generic signature. - if (const auto protoTy = dyn_cast<ProtocolType>(existential)) { + if (const auto protoTy = dyn_cast<ProtocolType>(constraint)) { return protoTy->getDecl()->getGenericSignature().getCanonicalSignature(); } - auto found = getImpl().ExistentialSignatures.find(existential); + auto found = getImpl().ExistentialSignatures.find(constraint); if (found != getImpl().ExistentialSignatures.end()) return found->second; @@ -5007,7 +5029,7 @@ CanGenericSignature ASTContext::getOpenedArchetypeSignature(Type type) { GenericTypeParamType::get(/*type sequence*/ false, /*depth*/ 0, /*index*/ 0, *this); Requirement requirement(RequirementKind::Conformance, genericParam, - existential); + constraint); auto genericSig = buildGenericSignature(*this, GenericSignature(), {genericParam}, @@ -5016,7 +5038,7 @@ CanGenericSignature ASTContext::getOpenedArchetypeSignature(Type type) { CanGenericSignature canGenericSig(genericSig); auto result = getImpl().ExistentialSignatures.insert( - std::make_pair(existential, canGenericSig)); + std::make_pair(constraint, canGenericSig)); assert(result.second); (void) result; diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 698da2641b787..149474bd664eb 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -70,8 +70,9 @@ TypeDecl *swift::Demangle::getTypeDeclForUSR(ASTContext &ctx, return getTypeDeclForMangling(ctx, mangling); } -Type ASTBuilder::decodeMangledType(NodePointer node) { - return swift::Demangle::decodeMangledType(*this, node).getType(); +Type ASTBuilder::decodeMangledType(NodePointer node, bool forRequirement) { + return swift::Demangle::decodeMangledType(*this, node, forRequirement) + .getType(); } TypeDecl *ASTBuilder::createTypeDecl(NodePointer node) { @@ -578,18 +579,19 @@ Type ASTBuilder::createImplFunctionType( Type ASTBuilder::createProtocolCompositionType( ArrayRef<ProtocolDecl *> protocols, Type superclass, - bool isClassBound) { + bool isClassBound, + bool forRequirement) { std::vector<Type> members; for (auto protocol : protocols) members.push_back(protocol->getDeclaredInterfaceType()); if (superclass && superclass->getClassOrBoundGenericClass()) members.push_back(superclass); + Type composition = ProtocolCompositionType::get(Ctx, members, isClassBound); - if (Ctx.LangOpts.EnableExplicitExistentialTypes && - !(composition->isAny() || composition->isAnyObject())) { - composition = ExistentialType::get(composition); - } - return composition; + if (forRequirement) + return composition; + + return ExistentialType::get(composition); } static MetatypeRepresentation diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index a0dc3450413e3..4f9cdf3a32be2 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -4852,6 +4852,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> { isSimpleUnderPrintOptions(opaque->getExistentialType()); } llvm_unreachable("bad opaque-return-type printing mode"); + } else if (auto existential = dyn_cast<ExistentialType>(T.getPointer())) { + if (!Options.PrintExplicitAny) + return isSimpleUnderPrintOptions(existential->getConstraintType()); } return T->hasSimpleTypeRepr(); } @@ -5272,9 +5275,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> { } } - auto &ctx = T->getASTContext(); - if (T->is<ExistentialMetatypeType>() && - ctx.LangOpts.EnableExplicitExistentialTypes) + if (T->is<ExistentialMetatypeType>() && Options.PrintExplicitAny) Printer << "any "; printWithParensIfNotSimple(T->getInstanceType()); @@ -5282,7 +5283,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> { // We spell normal metatypes of existential types as .Protocol. if (isa<MetatypeType>(T) && T->getInstanceType()->isAnyExistentialType() && - !ctx.LangOpts.EnableExplicitExistentialTypes) { + !Options.PrintExplicitAny) { Printer << ".Protocol"; } else { Printer << ".Type"; @@ -5875,7 +5876,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> { } void visitExistentialType(ExistentialType *T) { - Printer << "any "; + if (Options.PrintExplicitAny) + Printer << "any "; + visit(T->getConstraintType()); } diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp index b4f4c6931ac52..e05a901e6e1b6 100644 --- a/lib/AST/ASTVerifier.cpp +++ b/lib/AST/ASTVerifier.cpp @@ -2067,7 +2067,10 @@ class Verifier : public ASTWalker { abort(); } - checkSameType(E->getBase()->getType(), metatype->getInstanceType(), + auto instance = metatype->getInstanceType(); + if (auto existential = metatype->getAs<ExistentialMetatypeType>()) + instance = existential->getExistentialInstanceType(); + checkSameType(E->getBase()->getType(), instance, "base type of .Type expression"); verifyCheckedBase(E); } @@ -3422,11 +3425,12 @@ class Verifier : public ASTWalker { } Type checkExceptionTypeExists(const char *where) { - auto exn = Ctx.getErrorDecl(); - if (exn) return exn->getDeclaredInterfaceType(); + if (!Ctx.getErrorDecl()) { + Out << "exception type does not exist in " << where << "\n"; + abort(); + } - Out << "exception type does not exist in " << where << "\n"; - abort(); + return Ctx.getErrorExistentialType(); } bool isGoodSourceRange(SourceRange SR) { diff --git a/lib/AST/ClangTypeConverter.cpp b/lib/AST/ClangTypeConverter.cpp index 7a1a4eca5b6f4..33c9ff575c232 100644 --- a/lib/AST/ClangTypeConverter.cpp +++ b/lib/AST/ClangTypeConverter.cpp @@ -750,6 +750,11 @@ ClangTypeConverter::visitProtocolCompositionType(ProtocolCompositionType *type) return clangCtx.getObjCObjectPointerType(clangType); } +clang::QualType +ClangTypeConverter::visitExistentialType(ExistentialType *type) { + return visit(type->getConstraintType()); +} + clang::QualType ClangTypeConverter::visitBuiltinRawPointerType(BuiltinRawPointerType *type) { return ClangASTContext.VoidPtrTy; @@ -828,6 +833,9 @@ clang::QualType ClangTypeConverter::convert(Type type) { return it->second; // Try to do this without making cache entries for obvious cases. + if (auto existential = type->getAs<ExistentialType>()) + type = existential->getConstraintType(); + if (auto nominal = type->getAs<NominalType>()) { auto decl = nominal->getDecl(); if (auto clangDecl = decl->getClangDecl()) { diff --git a/lib/AST/ClangTypeConverter.h b/lib/AST/ClangTypeConverter.h index d14a930fe6e13..d4ba69e33cf8c 100644 --- a/lib/AST/ClangTypeConverter.h +++ b/lib/AST/ClangTypeConverter.h @@ -122,6 +122,7 @@ class ClangTypeConverter : clang::QualType visitEnumType(EnumType *type); clang::QualType visitFunctionType(FunctionType *type); clang::QualType visitProtocolCompositionType(ProtocolCompositionType *type); + clang::QualType visitExistentialType(ExistentialType *type); clang::QualType visitBuiltinRawPointerType(BuiltinRawPointerType *type); clang::QualType visitBuiltinIntegerType(BuiltinIntegerType *type); clang::QualType visitBuiltinFloatType(BuiltinFloatType *type); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 39547a9e1aa9e..dd7995158f2dd 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -5164,7 +5164,10 @@ findProtocolSelfReferences(const ProtocolDecl *proto, Type type, return SelfReferenceInfo::forSelfRef(SelfReferencePosition::Invariant); // Protocol compositions preserve variance. - if (auto *comp = type->getAs<ProtocolCompositionType>()) { + auto constraint = type; + if (auto existential = constraint->getAs<ExistentialType>()) + constraint = existential->getConstraintType(); + if (auto *comp = constraint->getAs<ProtocolCompositionType>()) { // 'Self' may be referenced only in a superclass component. if (const auto superclass = comp->getSuperclass()) { return findProtocolSelfReferences(proto, superclass, position); diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp index 691c3b7b48166..f27104ed2bdc3 100644 --- a/lib/AST/DiagnosticEngine.cpp +++ b/lib/AST/DiagnosticEngine.cpp @@ -549,6 +549,24 @@ static bool typeSpellingIsAmbiguous(Type type, auto argType = arg.getAsType(); if (argType && argType->getWithoutParens().getPointer() != type.getPointer() && argType->getWithoutParens().getString(PO) == type.getString(PO)) { + // Currently, existential types are spelled the same way + // as protocols and compositions. We can remove this once + // existenials are printed with 'any'. + if (type->is<ExistentialType>() || argType->isExistentialType()) { + auto constraint = type; + if (auto existential = type->getAs<ExistentialType>()) + constraint = existential->getConstraintType(); + + auto argConstraint = argType; + if (auto existential = argType->getAs<ExistentialType>()) + argConstraint = existential->getConstraintType(); + + if (constraint.getPointer() != argConstraint.getPointer()) + return true; + + continue; + } + return true; } } diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp index f223f310a0e61..7f7e7c4ffff91 100644 --- a/lib/AST/GenericSignatureBuilder.cpp +++ b/lib/AST/GenericSignatureBuilder.cpp @@ -4500,7 +4500,8 @@ ConstraintResult GenericSignatureBuilder::addTypeRequirement( } // Check whether we have a reasonable constraint type at all. - if (!constraintType->isExistentialType() && + if (!constraintType->is<ProtocolType>() && + !constraintType->is<ProtocolCompositionType>() && !constraintType->getClassOrBoundGenericClass()) { if (source.getLoc().isValid() && !constraintType->hasError()) { Impl->HadAnyError = true; @@ -6292,8 +6293,16 @@ GenericSignatureBuilder::finalize(TypeArrayView<GenericTypeParamType> genericPar auto source = constraint.source; auto loc = source->getLoc(); + // FIXME: The constraint string is printed directly here because + // the current default is to not print `any` for existential + // types, but this error message is super confusing without `any` + // if the user wrote it explicitly. + PrintOptions options; + options.PrintExplicitAny = true; + auto constraintString = constraintType.getString(options); + Diags.diagnose(loc, diag::requires_conformance_nonprotocol, - subjectType, constraintType); + subjectType, constraintString); auto getNameWithoutSelf = [&](std::string subjectTypeName) { std::string selfSubstring = "Self."; @@ -6311,7 +6320,7 @@ GenericSignatureBuilder::finalize(TypeArrayView<GenericTypeParamType> genericPar auto subjectTypeName = subjectType.getString(); auto subjectTypeNameWithoutSelf = getNameWithoutSelf(subjectTypeName); Diags.diagnose(loc, diag::requires_conformance_nonprotocol_fixit, - subjectTypeNameWithoutSelf, constraintType.getString()) + subjectTypeNameWithoutSelf, constraintString) .fixItReplace(loc, " == "); } } diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 07274fee10894..c406e45c9f242 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -978,13 +978,17 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) { // existential to an archetype parameter, so for now we restrict this to // @objc protocols and marker protocols. if (!layout.isObjC() && !protocol->isMarkerProtocol()) { + auto constraint = type; + if (auto existential = constraint->getAs<ExistentialType>()) + constraint = existential->getConstraintType(); + // There's a specific exception for protocols with self-conforming // witness tables, but the existential has to be *exactly* that type. // TODO: synthesize witness tables on-demand for protocol compositions // that can satisfy the requirement. if (protocol->requiresSelfConformanceWitnessTable() && - type->is<ProtocolType>() && - type->castTo<ProtocolType>()->getDecl() == protocol) + constraint->is<ProtocolType>() && + constraint->castTo<ProtocolType>()->getDecl() == protocol) return ProtocolConformanceRef(ctx.getSelfConformance(protocol)); return ProtocolConformanceRef::forInvalid(); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1046d859eff7c..e27fa2f517438 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -104,6 +104,8 @@ NominalTypeDecl *CanType::getAnyNominal() const { } GenericTypeDecl *CanType::getAnyGeneric() const { + if (auto existential = dyn_cast<ExistentialType>(*this)) + return existential->getConstraintType()->getAnyGeneric(); if (auto Ty = dyn_cast<AnyGenericType>(*this)) return Ty->getDecl(); return nullptr; @@ -464,6 +466,8 @@ Type TypeBase::eraseOpenedExistential(OpenedArchetypeType *opened) { auto instanceType = metatypeType->getInstanceType(); if (instanceType->hasOpenedExistential()) { instanceType = instanceType->eraseOpenedExistential(opened); + if (auto existential = instanceType->getAs<ExistentialType>()) + instanceType = existential->getConstraintType(); return ExistentialMetatypeType::get(instanceType); } } @@ -1199,6 +1203,9 @@ Type TypeBase::replaceSelfParameterType(Type newSelf) { /// Look through a metatype, or just return the original type if it is /// not a metatype. Type TypeBase::getMetatypeInstanceType() { + if (auto existentialMetaType = getAs<ExistentialMetatypeType>()) + return existentialMetaType->getExistentialInstanceType(); + if (auto metaTy = getAs<AnyMetatypeType>()) return metaTy->getInstanceType(); @@ -1494,7 +1501,7 @@ CanType TypeBase::computeCanonicalType() { case TypeKind::Existential: { auto *existential = cast<ExistentialType>(this); auto constraint = existential->getConstraintType()->getCanonicalType(); - Result = ExistentialType::get(constraint); + Result = ExistentialType::get(constraint).getPointer(); break; } case TypeKind::ExistentialMetatype: { @@ -2638,7 +2645,7 @@ getForeignRepresentable(Type type, ForeignLanguage language, // If type has an error let's fail early. if (type->hasError()) return failure(); - + // Look through one level of optional type, but remember that we did. bool wasOptional = false; if (auto valueType = type->getOptionalObjectType()) { @@ -2646,6 +2653,9 @@ getForeignRepresentable(Type type, ForeignLanguage language, wasOptional = true; } + if (auto existential = type->getAs<ExistentialType>()) + type = existential->getConstraintType(); + // Objective-C object types, including metatypes. if (language == ForeignLanguage::ObjectiveC) { auto representable = getObjCObjectRepresentable(type, dc); @@ -3237,9 +3247,11 @@ Type ArchetypeType::getExistentialType() const { for (auto proto : getConformsTo()) { constraintTypes.push_back(proto->getDeclaredInterfaceType()); } - return ProtocolCompositionType::get( - const_cast<ArchetypeType*>(this)->getASTContext(), constraintTypes, - requiresClass()); + auto &ctx = const_cast<ArchetypeType*>(this)->getASTContext(); + auto constraint = ProtocolCompositionType::get( + ctx, constraintTypes, requiresClass()); + + return ExistentialType::get(constraint); } PrimaryArchetypeType::PrimaryArchetypeType(const ASTContext &Ctx, @@ -5550,6 +5562,10 @@ bool Type::isPrivateStdlibType(bool treatNonBuiltinProtocolsAsPublic) const { if (!Ty) return false; + if (auto existential = dyn_cast<ExistentialType>(Ty.getPointer())) + return existential->getConstraintType() + .isPrivateStdlibType(treatNonBuiltinProtocolsAsPublic); + // A 'public' typealias can have an 'internal' type. if (auto *NAT = dyn_cast<TypeAliasType>(Ty.getPointer())) { auto *AliasDecl = NAT->getDecl(); @@ -5734,7 +5750,7 @@ SILBoxType::SILBoxType(ASTContext &C, Type TypeBase::openAnyExistentialType(OpenedArchetypeType *&opened) { assert(isAnyExistentialType()); if (auto metaty = getAs<ExistentialMetatypeType>()) { - opened = OpenedArchetypeType::get(metaty->getInstanceType()); + opened = OpenedArchetypeType::get(metaty->getExistentialInstanceType()); if (metaty->hasRepresentation()) return MetatypeType::get(opened, metaty->getRepresentation()); else diff --git a/lib/AST/TypeJoinMeet.cpp b/lib/AST/TypeJoinMeet.cpp index 403eb0417dc83..2c8db30bae1f6 100644 --- a/lib/AST/TypeJoinMeet.cpp +++ b/lib/AST/TypeJoinMeet.cpp @@ -66,6 +66,7 @@ struct TypeJoin : CanTypeVisitor<TypeJoin, CanType> { CanType visitBoundGenericStructType(CanType second); CanType visitMetatypeType(CanType second); CanType visitExistentialMetatypeType(CanType second); + CanType visitExistentialType(CanType second); CanType visitModuleType(CanType second); CanType visitDynamicSelfType(CanType second); CanType visitArchetypeType(CanType second); @@ -271,6 +272,24 @@ CanType TypeJoin::visitExistentialMetatypeType(CanType second) { return ExistentialMetatypeType::get(joinInstance)->getCanonicalType(); } +CanType TypeJoin::visitExistentialType(CanType second) { + assert(First != second); + + if (First->getKind() != second->getKind()) + return TheAnyType; + + auto firstConstraint = First->castTo<ExistentialType>() + ->getConstraintType()->getCanonicalType(); + auto secondConstraint = second->castTo<ExistentialType>() + ->getConstraintType()->getCanonicalType(); + + auto joinInstance = join(firstConstraint, secondConstraint); + if (!joinInstance) + return CanType(); + + return ExistentialType::get(joinInstance)->getCanonicalType(); +} + CanType TypeJoin::visitModuleType(CanType second) { assert(First != second); diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 91d1356458d76..59f8e1317939a 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -6244,6 +6244,9 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl, // Local function to add a known protocol only when the // underlying type conforms to it. auto computedNominal = computedPropertyUnderlyingType->getAnyNominal(); + if (auto existential = + computedPropertyUnderlyingType->getAs<ExistentialType>()) + computedNominal = existential->getConstraintType()->getAnyNominal(); auto transferKnown = [&](KnownProtocolKind kind) { if (!computedNominal) return false; diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 1273db09499a0..ff8f530bcd18f 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -1049,9 +1049,10 @@ namespace { if (memberTypes.empty()) hasExplicitAnyObject = true; - Type importedTypeArg = ProtocolCompositionType::get( - Impl.SwiftContext, memberTypes, - hasExplicitAnyObject); + Type importedTypeArg = ExistentialType::get( + ProtocolCompositionType::get( + Impl.SwiftContext, memberTypes, + hasExplicitAnyObject)); importedTypeArgs.push_back(importedTypeArg); } } @@ -1180,6 +1181,9 @@ namespace { } } + if (bridgedType->isConstraintType()) + bridgedType = ExistentialType::get(bridgedType); + return { importedType, ImportHint(ImportHint::ObjCBridged, bridgedType) }; } @@ -1200,9 +1204,9 @@ namespace { members.push_back(proto->getDeclaredInterfaceType()); } - importedType = ProtocolCompositionType::get(Impl.SwiftContext, - members, - /*HasExplicitAnyObject=*/false); + importedType = ExistentialType::get( + ProtocolCompositionType::get(Impl.SwiftContext, members, + /*HasExplicitAnyObject=*/false)); } // Class or Class<P> maps to an existential metatype. @@ -2497,7 +2501,7 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType( bool paramIsIUO; if (kind == SpecialMethodKind::NSDictionarySubscriptGetter && paramTy->isObjCIdType()) { - swiftParamTy = SwiftContext.getNSCopyingType(); + swiftParamTy = ExistentialType::get(SwiftContext.getNSCopyingType()); if (!swiftParamTy) return {Type(), false}; if (optionalityOfParam != OTK_None) diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp index 917a2474c0f35..8035c45f87886 100644 --- a/lib/IDE/Refactoring.cpp +++ b/lib/IDE/Refactoring.cpp @@ -7831,7 +7831,8 @@ class AsyncConverter : private SourceEntityWalker { const AsyncHandlerDesc &HandlerDesc) { // If the error type is already Error, we can pass it as-is. auto ErrorType = *HandlerDesc.getErrorType(); - if (ErrorType->getCanonicalType() == getASTContext().getExceptionType()) { + if (ErrorType->getCanonicalType() == + getASTContext().getErrorExistentialType()) { OS << ErrorName; return; } diff --git a/lib/IRGen/DebugTypeInfo.cpp b/lib/IRGen/DebugTypeInfo.cpp index 779f30d9c782a..8ef7826cc4762 100644 --- a/lib/IRGen/DebugTypeInfo.cpp +++ b/lib/IRGen/DebugTypeInfo.cpp @@ -158,6 +158,8 @@ TypeDecl *DebugTypeInfo::getDecl() const { return UBG->getDecl(); if (auto *BG = dyn_cast<BoundGenericType>(Type)) return BG->getDecl(); + if (auto *E = dyn_cast<ExistentialType>(Type)) + return E->getConstraintType()->getAnyNominal(); return nullptr; } diff --git a/lib/IRGen/GenBuiltin.cpp b/lib/IRGen/GenBuiltin.cpp index e6d483391bbed..60e7f20738266 100644 --- a/lib/IRGen/GenBuiltin.cpp +++ b/lib/IRGen/GenBuiltin.cpp @@ -592,10 +592,9 @@ if (Builtin.ID == BuiltinValueKind::id) { \ auto *fn = cast<llvm::Function>(IGF.IGM.getWillThrowFn()); auto error = args.claimNext(); + auto errorTy = IGF.IGM.Context.getErrorExistentialType(); auto errorBuffer = IGF.getCalleeErrorResultSlot( - SILType::getPrimitiveObjectType(IGF.IGM.Context.getErrorDecl() - ->getDeclaredInterfaceType() - ->getCanonicalType())); + SILType::getPrimitiveObjectType(errorTy)); IGF.Builder.CreateStore(error, errorBuffer); auto context = llvm::UndefValue::get(IGF.IGM.Int8PtrTy); diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 070fafebb5316..fb64cc9ee854f 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -97,6 +97,22 @@ class EqualUpToClangTypes }; }; +static bool equalWithoutExistentialTypes(Type t1, Type t2) { + if (!t1->getASTContext().LangOpts.EnableExplicitExistentialTypes) + return false; + + auto withoutExistentialTypes = [](Type type) -> Type { + return type.transform([](Type type) -> Type { + if (auto existential = type->getAs<ExistentialType>()) + return existential->getConstraintType(); + return type; + }); + }; + + return withoutExistentialTypes(t1) + ->isEqual(withoutExistentialTypes(t2)); +} + class IRGenDebugInfoImpl : public IRGenDebugInfo { friend class IRGenDebugInfoImpl; const IRGenOptions &Opts; @@ -900,6 +916,9 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { Ty->dump(llvm::errs()); abort(); } else if (!Reconstructed->isEqual(Ty) && + // FIXME: Some existential types are reconstructed without + // an explicit ExistentialType wrapping the constraint. + !equalWithoutExistentialTypes(Reconstructed, Ty) && !EqualUpToClangTypes().check(Reconstructed, Ty)) { // [FIXME: Include-Clang-type-in-mangling] Remove second check llvm::errs() << "Incorrect reconstructed type for " << Result << "\n"; diff --git a/lib/IRGen/IRGenMangler.cpp b/lib/IRGen/IRGenMangler.cpp index ea92243bb26b8..b1555583bf151 100644 --- a/lib/IRGen/IRGenMangler.cpp +++ b/lib/IRGen/IRGenMangler.cpp @@ -216,6 +216,8 @@ std::string IRGenMangler::mangleTypeForLLVMTypeName(CanType Ty) { // To make LLVM IR more readable we always add a 'T' prefix so that type names // don't start with a digit and don't need to be quoted. Buffer << 'T'; + if (auto existential = Ty->getAs<ExistentialType>()) + Ty = existential->getConstraintType()->getCanonicalType(); if (auto P = dyn_cast<ProtocolType>(Ty)) { appendProtocolName(P->getDecl(), /*allowStandardSubstitution=*/false); appendOperator("P"); diff --git a/lib/SIL/IR/SILType.cpp b/lib/SIL/IR/SILType.cpp index 046e68782487d..d9faf0009361d 100644 --- a/lib/SIL/IR/SILType.cpp +++ b/lib/SIL/IR/SILType.cpp @@ -45,7 +45,7 @@ CanArchetypeType swift::getOpenedArchetypeOf(CanType Ty) { } SILType SILType::getExceptionType(const ASTContext &C) { - return SILType::getPrimitiveObjectType(C.getExceptionType()); + return SILType::getPrimitiveObjectType(C.getErrorExistentialType()); } SILType SILType::getNativeObjectType(const ASTContext &C) { diff --git a/lib/SIL/Utils/BasicBlockUtils.cpp b/lib/SIL/Utils/BasicBlockUtils.cpp index 4dcdc2800d1a4..3a1f46bdd532f 100644 --- a/lib/SIL/Utils/BasicBlockUtils.cpp +++ b/lib/SIL/Utils/BasicBlockUtils.cpp @@ -144,8 +144,8 @@ void swift::getEdgeArgs(TermInst *T, unsigned edgeIdx, SILBasicBlock *newEdgeBB, case 1: { assert(AACI->getErrorBB()); auto &C = AACI->getFunction()->getASTContext(); - auto errorTy = C.getErrorDecl()->getDeclaredType(); - auto errorSILTy = SILType::getPrimitiveObjectType(errorTy->getCanonicalType()); + auto errorTy = C.getErrorExistentialType(); + auto errorSILTy = SILType::getPrimitiveObjectType(errorTy); // error BB. this takes the error value argument args.push_back( newEdgeBB->createPhiArgument(errorSILTy, OwnershipKind::Owned)); diff --git a/lib/SIL/Utils/DynamicCasts.cpp b/lib/SIL/Utils/DynamicCasts.cpp index 550a0794184b2..ae167f9c9ec57 100644 --- a/lib/SIL/Utils/DynamicCasts.cpp +++ b/lib/SIL/Utils/DynamicCasts.cpp @@ -468,8 +468,7 @@ swift::classifyDynamicCast(ModuleDecl *M, : DynamicCastFeasibility::WillFail; } - if (targetMetatype.isAnyExistentialType() && - (isa<ProtocolType>(target) || isa<ProtocolCompositionType>(target))) { + if (targetMetatype.isAnyExistentialType() && target->isExistentialType()) { auto Feasibility = classifyDynamicCastToProtocol(M, source, target, isWholeModuleOpts); // Cast from existential metatype to existential metatype may still diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index 3bfaee4e0a897..a81dcfd3fa25a 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -2960,8 +2960,19 @@ class SILVerifier : public SILVerifierBase<SILVerifier> { "value_metatype instruction must have a metatype representation"); require(MI->getOperand()->getType().isAnyExistentialType(), "existential_metatype operand must be of protocol type"); + + // The result of an existential_metatype instruction is an existential + // metatype with the same constraint type as its existential operand. auto formalInstanceTy = MI->getType().castTo<ExistentialMetatypeType>().getInstanceType(); + if (M->getASTContext().LangOpts.EnableExplicitExistentialTypes && + formalInstanceTy->isConstraintType() && + !(formalInstanceTy->isAny() || formalInstanceTy->isAnyObject())) { + require(MI->getOperand()->getType().is<ExistentialType>(), + "existential_metatype operand must be an existential type"); + formalInstanceTy = + ExistentialType::get(formalInstanceTy)->getCanonicalType(); + } require(isLoweringOf(MI->getOperand()->getType(), formalInstanceTy), "existential_metatype result must be formal metatype of " "lowered operand type"); @@ -5252,7 +5263,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> { require(AACI->getErrorBB()->getNumArguments() == 1, "error successor must take one argument"); auto arg = AACI->getErrorBB()->getArgument(0); - auto errorType = C.getErrorDecl()->getDeclaredType()->getCanonicalType(); + auto errorType = C.getErrorExistentialType(); requireSameType(arg->getType(), SILType::getPrimitiveObjectType(errorType), "error successor argument must have Error type"); diff --git a/lib/SILGen/ResultPlan.cpp b/lib/SILGen/ResultPlan.cpp index 8728c07973570..f229d5d497b40 100644 --- a/lib/SILGen/ResultPlan.cpp +++ b/lib/SILGen/ResultPlan.cpp @@ -508,7 +508,7 @@ class ForeignAsyncInitializationPlan final : public ResultPlan { auto continuationDecl = SGF.getASTContext().getUnsafeContinuationDecl(); auto errorTy = throws - ? SGF.getASTContext().getExceptionType() + ? SGF.getASTContext().getErrorExistentialType() : SGF.getASTContext().getNeverType(); auto continuationTy = BoundGenericType::get(continuationDecl, Type(), { calleeTypeInfo.substResultType, errorTy }) @@ -618,7 +618,7 @@ class ForeignAsyncInitializationPlan final : public ResultPlan { auto continuationDecl = SGF.getASTContext().getUnsafeContinuationDecl(); - auto errorTy = SGF.getASTContext().getExceptionType(); + auto errorTy = SGF.getASTContext().getErrorExistentialType(); auto continuationBGT = BoundGenericType::get(continuationDecl, Type(), {calleeTypeInfo.substResultType, errorTy}); @@ -666,9 +666,8 @@ class ForeignAsyncInitializationPlan final : public ResultPlan { SGF.B.emitBlock(errorBlock); Scope errorScope(SGF, loc); - - auto errorTy = SGF.getASTContext().getErrorDecl()->getDeclaredType() - ->getCanonicalType(); + + auto errorTy = SGF.getASTContext().getErrorExistentialType(); auto errorVal = SGF.B.createTermResult( SILType::getPrimitiveObjectType(errorTy), OwnershipKind::Owned); diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index f3febf7c8ed8f..bd85b869b83b9 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -168,6 +168,7 @@ getBridgingFn(Optional<SILDeclRef> &cacheSlot, #define REQUIRED(X) Types.get##X##Type() #define OPTIONAL(X) OptionalType::get(Types.get##X##Type()) +#define EXISTENTIAL(X) getASTContext().get##X##ExistentialType() #define GET_BRIDGING_FN(Module, FromKind, FromTy, ToKind, ToTy) \ SILDeclRef SILGenModule::get##FromTy##To##ToTy##Fn() { \ @@ -182,8 +183,8 @@ GET_BRIDGING_FN(Darwin, REQUIRED, Bool, REQUIRED, DarwinBoolean) GET_BRIDGING_FN(Darwin, REQUIRED, DarwinBoolean, REQUIRED, Bool) GET_BRIDGING_FN(ObjectiveC, REQUIRED, Bool, REQUIRED, ObjCBool) GET_BRIDGING_FN(ObjectiveC, REQUIRED, ObjCBool, REQUIRED, Bool) -GET_BRIDGING_FN(Foundation, OPTIONAL, NSError, REQUIRED, Error) -GET_BRIDGING_FN(Foundation, REQUIRED, Error, REQUIRED, NSError) +GET_BRIDGING_FN(Foundation, OPTIONAL, NSError, EXISTENTIAL, Error) +GET_BRIDGING_FN(Foundation, EXISTENTIAL, Error, REQUIRED, NSError) GET_BRIDGING_FN(WinSDK, REQUIRED, Bool, REQUIRED, WindowsBool) GET_BRIDGING_FN(WinSDK, REQUIRED, WindowsBool, REQUIRED, Bool) diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp index 1d9b726e7ec3c..c70dd365f471d 100644 --- a/lib/SILGen/SILGenBridging.cpp +++ b/lib/SILGen/SILGenBridging.cpp @@ -1252,7 +1252,7 @@ ManagedValue SILGenFunction::emitNativeToBridgedError(SILLocation loc, // FIXME: maybe we should use a different entrypoint for this case, to // avoid the code size and performance overhead of forming the box? nativeError = emitUnabstractedCast(*this, loc, nativeError, nativeType, - getASTContext().getExceptionType()); + getASTContext().getErrorExistentialType()); auto bridgeFn = emitGlobalFunctionRef(loc, SGM.getErrorToNSErrorFn()); auto bridgeFnType = bridgeFn->getType().castTo<SILFunctionType>(); diff --git a/lib/SILGen/SILGenBuiltin.cpp b/lib/SILGen/SILGenBuiltin.cpp index efa71d2a76708..10a75bbcf3b67 100644 --- a/lib/SILGen/SILGenBuiltin.cpp +++ b/lib/SILGen/SILGenBuiltin.cpp @@ -1564,8 +1564,7 @@ static ManagedValue emitBuiltinWithUnsafeContinuation( Scope errorScope(SGF, loc); - auto errorTy = SGF.getASTContext().getErrorDecl()->getDeclaredType() - ->getCanonicalType(); + auto errorTy = SGF.getASTContext().getErrorExistentialType(); auto errorVal = SGF.B.createTermResult( SILType::getPrimitiveObjectType(errorTy), OwnershipKind::Owned); diff --git a/lib/SILGen/SILGenConvert.cpp b/lib/SILGen/SILGenConvert.cpp index 20b353e50f822..8ec0c67263735 100644 --- a/lib/SILGen/SILGenConvert.cpp +++ b/lib/SILGen/SILGenConvert.cpp @@ -913,8 +913,11 @@ ManagedValue SILGenFunction::emitExistentialMetatypeToObject(SILLocation loc, ManagedValue SILGenFunction::emitProtocolMetatypeToObject(SILLocation loc, CanType inputTy, SILType resultTy) { - ProtocolDecl *protocol = inputTy->castTo<MetatypeType>() - ->getInstanceType()->castTo<ProtocolType>()->getDecl(); + auto protocolType = inputTy->castTo<MetatypeType>()->getInstanceType(); + if (auto existential = protocolType->getAs<ExistentialType>()) + protocolType = existential->getConstraintType(); + + ProtocolDecl *protocol = protocolType->castTo<ProtocolType>()->getDecl(); SILValue value = B.createObjCProtocol(loc, protocol, resultTy); diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 45d9840d9dd43..15f720d0c5746 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -1037,8 +1037,7 @@ SILValue SILGenFunction::emitTemporaryAllocation(SILLocation loc, SILType ty, if (auto *DRE = loc.getAsASTNode<DeclRefExpr>()) if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) if (!isa<ParamDecl>(VD) && VD->isImplicit() && - (VD->getType()->is<ProtocolType>() || - VD->getType()->is<ProtocolCompositionType>()) && + VD->getType()->isExistentialType() && VD->getType()->getExistentialLayout().isErrorExistential()) { DbgVar = SILDebugVariable(VD->isLet(), 0); loc = SILLocation(VD); diff --git a/lib/SILGen/SILGenForeignError.cpp b/lib/SILGen/SILGenForeignError.cpp index 4c95fc44deaa7..30edca104fa74 100644 --- a/lib/SILGen/SILGenForeignError.cpp +++ b/lib/SILGen/SILGenForeignError.cpp @@ -134,7 +134,7 @@ namespace { SILValue emitBridged(SILGenFunction &SGF, SILLocation loc, CanType bridgedErrorProto) const override { auto nativeErrorType = NativeError->getType().getASTType(); - assert(nativeErrorType == SGF.SGM.getASTContext().getExceptionType()); + assert(nativeErrorType == SGF.SGM.getASTContext().getErrorExistentialType()); SILValue bridgedError = SGF.emitNativeToBridgedError(loc, SGF.emitManagedRValueWithCleanup(NativeError), diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp index a044e6c57447f..7f6c109adb83c 100644 --- a/lib/SILGen/SILGenPoly.cpp +++ b/lib/SILGen/SILGenPoly.cpp @@ -220,7 +220,7 @@ static ManagedValue emitTransformExistential(SILGenFunction &SGF, fromInstanceType = cast<MetatypeType>(fromInstanceType) .getInstanceType(); toInstanceType = cast<ExistentialMetatypeType>(toInstanceType) - .getInstanceType(); + ->getExistentialInstanceType()->getCanonicalType(); } ArrayRef<ProtocolConformanceRef> conformances = @@ -3052,8 +3052,13 @@ buildThunkSignature(SILGenFunction &SGF, // Add a new generic parameter to replace the opened existential. auto *newGenericParam = GenericTypeParamType::get(/*type sequence*/ false, depth, 0, ctx); + + auto constraint = openedExistential->getOpenedExistentialType(); + if (auto existential = constraint->getAs<ExistentialType>()) + constraint = existential->getConstraintType(); + Requirement newRequirement(RequirementKind::Conformance, newGenericParam, - openedExistential->getOpenedExistentialType()); + constraint); auto genericSig = buildGenericSignature(ctx, baseGenericSig, { newGenericParam }, diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp index 08f2af1512c12..20f0383d1cf24 100644 --- a/lib/SILGen/SILGenType.cpp +++ b/lib/SILGen/SILGenType.cpp @@ -842,7 +842,7 @@ static SILFunction *emitSelfConformanceWitness(SILGenModule &SGM, ProtocolConformanceRef(conformance)); // Open the protocol type. - auto openedType = OpenedArchetypeType::get(protocolType); + auto openedType = OpenedArchetypeType::get(protocol->getExistentialType()); // Form the substitutions for calling the witness. auto witnessSubs = SubstitutionMap::getProtocolSubstitutions(protocol, diff --git a/lib/SILOptimizer/Differentiation/Thunk.cpp b/lib/SILOptimizer/Differentiation/Thunk.cpp index e9f5a88cafc7d..2f394f4335fa5 100644 --- a/lib/SILOptimizer/Differentiation/Thunk.cpp +++ b/lib/SILOptimizer/Differentiation/Thunk.cpp @@ -66,8 +66,13 @@ CanGenericSignature buildThunkSignature(SILFunction *fn, bool inheritGenericSig, // Add a new generic parameter to replace the opened existential. auto *newGenericParam = GenericTypeParamType::get(/*type sequence*/ false, depth, 0, ctx); + + auto constraint = openedExistential->getOpenedExistentialType(); + if (auto existential = constraint->getAs<ExistentialType>()) + constraint = existential->getConstraintType(); + Requirement newRequirement(RequirementKind::Conformance, newGenericParam, - openedExistential->getOpenedExistentialType()); + constraint); auto genericSig = buildGenericSignature(ctx, baseGenericSig, { newGenericParam }, diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialSpecializer.cpp b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialSpecializer.cpp index b1decdc3830da..57aab7934a478 100644 --- a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialSpecializer.cpp +++ b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialSpecializer.cpp @@ -95,12 +95,16 @@ bool ExistentialSpecializer::findConcreteTypeFromSoleConformingType( auto ArgType = Arg->getType(); auto SwiftArgType = ArgType.getASTType(); + CanType constraint = SwiftArgType; + if (auto existential = constraint->getAs<ExistentialType>()) + constraint = existential->getConstraintType()->getCanonicalType(); + /// Do not handle composition types yet. - if (isa<ProtocolCompositionType>(SwiftArgType)) + if (isa<ProtocolCompositionType>(constraint)) return false; assert(ArgType.isExistentialType()); /// Find the protocol decl. - auto *PD = dyn_cast<ProtocolDecl>(SwiftArgType->getAnyNominal()); + auto *PD = dyn_cast<ProtocolDecl>(constraint->getAnyNominal()); if (!PD) return false; diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp index 47173c70b4aac..5b68e78386ad8 100644 --- a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp +++ b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp @@ -304,12 +304,17 @@ void ExistentialTransform::convertExistentialArgTypesToGenericArgTypes( auto ¶m = params[Idx]; auto PType = param.getArgumentType(M, FTy, F->getTypeExpansionContext()); assert(PType.isExistentialType()); + + CanType constraint = PType; + if (auto existential = PType->getAs<ExistentialType>()) + constraint = existential->getConstraintType()->getCanonicalType(); + /// Generate new generic parameter. auto *NewGenericParam = GenericTypeParamType::get(/*type sequence*/ false, Depth, GPIdx++, Ctx); genericParams.push_back(NewGenericParam); Requirement NewRequirement(RequirementKind::Conformance, NewGenericParam, - PType); + constraint); requirements.push_back(NewRequirement); ArgToGenericTypeMap.insert( std::pair<int, GenericTypeParamType *>(Idx, NewGenericParam)); diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp index cbeac56f61175..de244e631fbe9 100644 --- a/lib/Sema/BuilderTransform.cpp +++ b/lib/Sema/BuilderTransform.cpp @@ -914,14 +914,14 @@ class BuilderClosureVisitor /// Visit a throw statement, which never produces a result. VarDecl *visitThrowStmt(ThrowStmt *throwStmt) { - Type exnType = ctx.getErrorDecl()->getDeclaredInterfaceType(); - if (!exnType) { + if (!ctx.getErrorDecl()) { hadError = true; } if (cs) { SolutionApplicationTarget target( - throwStmt->getSubExpr(), dc, CTP_ThrowStmt, exnType, + throwStmt->getSubExpr(), dc, CTP_ThrowStmt, + ctx.getErrorExistentialType(), /*isDiscarded=*/false); if (cs->generateConstraints(target, FreeTypeVariableBinding::Disallow)) hadError = true; diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 9824e6bd3825d..480d93d2374dc 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -1379,6 +1379,8 @@ namespace { baseIsInstance = false; isExistentialMetatype = baseMeta->is<ExistentialMetatypeType>(); baseTy = baseMeta->getInstanceType(); + if (auto existential = baseTy->getAs<ExistentialType>()) + baseTy = existential->getConstraintType(); // A valid reference to a static member (computed property or a method) // declared on a protocol is only possible if result type conforms to @@ -5346,10 +5348,8 @@ Expr *ExprRewriter::coerceSuperclass(Expr *expr, Type toType) { while (fromInstanceType->is<AnyMetatypeType>() && toInstanceType->is<MetatypeType>()) { - fromInstanceType = fromInstanceType->castTo<AnyMetatypeType>() - ->getInstanceType(); - toInstanceType = toInstanceType->castTo<MetatypeType>() - ->getInstanceType(); + fromInstanceType = fromInstanceType->getMetatypeInstanceType(); + toInstanceType = toInstanceType->getMetatypeInstanceType(); } if (fromInstanceType->is<ArchetypeType>()) { @@ -5422,7 +5422,7 @@ Expr *ExprRewriter::coerceExistential(Expr *expr, Type toType) { toInstanceType->is<ExistentialMetatypeType>()) { if (!fromInstanceType->is<UnresolvedType>()) fromInstanceType = fromInstanceType->castTo<AnyMetatypeType>()->getInstanceType(); - toInstanceType = toInstanceType->castTo<ExistentialMetatypeType>()->getInstanceType(); + toInstanceType = toInstanceType->castTo<ExistentialMetatypeType>()->getExistentialInstanceType(); } ASTContext &ctx = cs.getASTContext(); @@ -7511,7 +7511,7 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType, openedInstanceTy = metaTy->getInstanceType(); existentialInstanceTy = existentialInstanceTy ->castTo<ExistentialMetatypeType>() - ->getInstanceType(); + ->getExistentialInstanceType(); } assert(openedInstanceTy->castTo<OpenedArchetypeType>() ->getOpenedExistentialType() diff --git a/lib/Sema/CSClosure.cpp b/lib/Sema/CSClosure.cpp index c665235bece3e..6bcd97622ebc4 100644 --- a/lib/Sema/CSClosure.cpp +++ b/lib/Sema/CSClosure.cpp @@ -621,13 +621,12 @@ class ClosureConstraintGenerator assert(isSupportedMultiStatementClosure() && "Unsupported statement: Throw"); - Type errType = - cs.getASTContext().getErrorDecl()->getDeclaredInterfaceType(); - if (!errType) { + if (!cs.getASTContext().getErrorDecl()) { hadError = true; return; } + auto errType = cs.getASTContext().getErrorExistentialType(); auto *errorExpr = throwStmt->getSubExpr(); createConjunction( @@ -739,7 +738,7 @@ class ClosureConstraintGenerator auto *switchStmt = cast<SwitchStmt>(parent.get<Stmt *>()); contextualTy = cs.getType(switchStmt->getSubjectExpr()); } else if (parent.isStmt(StmtKind::DoCatch)) { - contextualTy = cs.getASTContext().getExceptionType(); + contextualTy = cs.getASTContext().getErrorExistentialType(); } else { hadError = true; return; diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 52b58b3808242..1418b0e7c4a6b 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -221,6 +221,10 @@ ValueDecl *RequirementFailure::getDeclRef() const { // diagnostic directly to its declaration without desugaring. if (auto *alias = dyn_cast<TypeAliasType>(type.getPointer())) return alias->getDecl(); + + if (auto existential = type->getAs<ExistentialType>()) + return existential->getConstraintType()->getAnyGeneric(); + return type->getAnyGeneric(); }; @@ -531,10 +535,14 @@ bool MissingConformanceFailure::diagnoseTypeCannotConform( return false; } + Type constraintType = nonConformingType; + if (auto existential = constraintType->getAs<ExistentialType>()) + constraintType = existential->getConstraintType(); + emitDiagnostic(diag::type_cannot_conform, nonConformingType->isExistentialType(), nonConformingType, - nonConformingType->isEqual(protocolType), + constraintType->isEqual(protocolType), protocolType); bool emittedSpecializedNote = false; @@ -2328,9 +2336,13 @@ bool ContextualFailure::diagnoseAsError() { if (CTP == CTP_ForEachStmt || CTP == CTP_ForEachSequence) { if (fromType->isAnyExistentialType()) { + Type constraintType = fromType; + if (auto existential = constraintType->getAs<ExistentialType>()) + constraintType = existential->getConstraintType(); + emitDiagnostic(diag::type_cannot_conform, /*isExistentialType=*/true, fromType, - fromType->isEqual(toType), toType); + constraintType->isEqual(toType), toType); emitDiagnostic(diag::only_concrete_types_conform_to_protocols); return true; } @@ -3063,7 +3075,10 @@ bool ContextualFailure::tryProtocolConformanceFixIt( // the protocols of the composition, then store the composition directly. // This is because we need to append 'Foo & Bar' instead of 'Foo, Bar' in // order to match the written type. - if (auto compositionTy = unwrappedToType->getAs<ProtocolCompositionType>()) { + auto constraint = unwrappedToType; + if (auto existential = constraint->getAs<ExistentialType>()) + constraint = existential->getConstraintType(); + if (auto compositionTy = constraint->getAs<ProtocolCompositionType>()) { if (compositionTy->getMembers().size() == missingProtoTypeStrings.size()) { missingProtoTypeStrings = {compositionTy->getString()}; } @@ -3651,7 +3666,8 @@ bool MissingMemberFailure::diagnoseAsError() { diagnostic.highlight(getSourceRange()) .highlight(nameLoc.getSourceRange()); correction->addFixits(diagnostic); - } else if (instanceTy->getAnyNominal() && + } else if ((instanceTy->getAnyNominal() || + instanceTy->is<ExistentialType>()) && getName().getBaseName() == DeclBaseName::createConstructor()) { auto &cs = getConstraintSystem(); @@ -4123,7 +4139,11 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { // If we are in a protocol extension of 'Proto' and we see // 'Proto.static', suggest 'Self.static' if (auto extensionContext = parent->getExtendedProtocolDecl()) { - if (extensionContext->getDeclaredType()->isEqual(instanceTy)) { + auto constraint = instanceTy; + if (auto existential = constraint->getAs<ExistentialType>()) + constraint = existential->getConstraintType(); + + if (extensionContext->getDeclaredType()->isEqual(constraint)) { Diag->fixItReplace(getSourceRange(), "Self"); } } @@ -6838,10 +6858,14 @@ bool AssignmentTypeMismatchFailure::diagnoseMissingConformance() const { auto retrieveProtocols = [](Type type, llvm::SmallPtrSetImpl<ProtocolDecl *> &members) { - if (auto *protocol = type->getAs<ProtocolType>()) + auto constraint = type; + if (auto existential = constraint->getAs<ExistentialType>()) + constraint = existential->getConstraintType(); + + if (auto *protocol = constraint->getAs<ProtocolType>()) members.insert(protocol->getDecl()); - if (auto *composition = type->getAs<ProtocolCompositionType>()) { + if (auto *composition = constraint->getAs<ProtocolCompositionType>()) { for (auto member : composition->getMembers()) { if (auto *protocol = member->getAs<ProtocolType>()) members.insert(protocol->getDecl()); diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 172e31d7ce545..1124286eefd70 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -2886,42 +2886,40 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2, return result; } - // Handle protocol compositions. - if (auto existential1 = type1->getAs<ProtocolCompositionType>()) { - if (auto existential2 = type2->getAs<ProtocolCompositionType>()) { - auto layout1 = existential1->getExistentialLayout(); - auto layout2 = existential2->getExistentialLayout(); - - // Explicit AnyObject and protocols must match exactly. - if (layout1.hasExplicitAnyObject != layout2.hasExplicitAnyObject) - return getTypeMatchFailure(locator); + // Handle existential types. + if (type1->isExistentialType() && type2->isExistentialType()) { + auto layout1 = type1->getExistentialLayout(); + auto layout2 = type2->getExistentialLayout(); - if (layout1.getProtocols().size() != layout2.getProtocols().size()) - return getTypeMatchFailure(locator); + // Explicit AnyObject and protocols must match exactly. + if (layout1.hasExplicitAnyObject != layout2.hasExplicitAnyObject) + return getTypeMatchFailure(locator); - for (unsigned i: indices(layout1.getProtocols())) { - if (!layout1.getProtocols()[i]->isEqual(layout2.getProtocols()[i])) - return getTypeMatchFailure(locator); - } + if (layout1.getProtocols().size() != layout2.getProtocols().size()) + return getTypeMatchFailure(locator); - // This is the only interesting case. We might have type variables - // on either side of the superclass constraint, so make sure we - // recursively call matchTypes() here. - if (layout1.explicitSuperclass || layout2.explicitSuperclass) { - if (!layout1.explicitSuperclass || !layout2.explicitSuperclass) - return getTypeMatchFailure(locator); + for (unsigned i: indices(layout1.getProtocols())) { + if (!layout1.getProtocols()[i]->isEqual(layout2.getProtocols()[i])) + return getTypeMatchFailure(locator); + } - auto result = matchTypes(layout1.explicitSuperclass, - layout2.explicitSuperclass, - ConstraintKind::Bind, subflags, - locator.withPathElement( - ConstraintLocator::ExistentialSuperclassType)); - if (result.isFailure()) - return result; - } + // This is the only interesting case. We might have type variables + // on either side of the superclass constraint, so make sure we + // recursively call matchTypes() here. + if (layout1.explicitSuperclass || layout2.explicitSuperclass) { + if (!layout1.explicitSuperclass || !layout2.explicitSuperclass) + return getTypeMatchFailure(locator); - return getTypeMatchSuccess(); + auto result = matchTypes(layout1.explicitSuperclass, + layout2.explicitSuperclass, + ConstraintKind::Bind, subflags, + locator.withPathElement( + ConstraintLocator::ExistentialSuperclassType)); + if (result.isFailure()) + return result; } + + return getTypeMatchSuccess(); } // Handle nominal types that are not directly generic. if (auto nominal1 = type1->getAs<NominalType>()) { @@ -6033,8 +6031,12 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, return true; return false; }; + + auto constraintType = meta1->getInstanceType(); + if (auto existential = constraintType->getAs<ExistentialType>()) + constraintType = existential->getConstraintType(); - if (auto protoTy = meta1->getInstanceType()->getAs<ProtocolType>()) { + if (auto protoTy = constraintType->getAs<ProtocolType>()) { if (protoTy->getDecl()->isObjC() && isProtocolClassType(type2)) { increaseScore(ScoreKind::SK_UserConversion); @@ -7007,7 +7009,7 @@ static bool isCastToExpressibleByNilLiteral(ConstraintSystem &cs, Type fromType, if (!nilLiteral) return false; - return toType->isEqual(nilLiteral->getDeclaredType()) && + return toType->isEqual(nilLiteral->getExistentialType()) && fromType->getOptionalObjectType(); } @@ -9808,7 +9810,7 @@ ConstraintSystem::simplifyOpenedExistentialOfConstraint( auto instanceTy = type2; if (auto metaTy = type2->getAs<ExistentialMetatypeType>()) { isMetatype = true; - instanceTy = metaTy->getInstanceType(); + instanceTy = metaTy->getExistentialInstanceType(); } assert(instanceTy->isExistentialType()); Type openedTy = OpenedArchetypeType::get(instanceTy); diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 258738a70b0b9..61042497b768b 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1767,6 +1767,13 @@ ConstraintSystem::getTypeOfMemberReference( auto memberTy = TypeChecker::substMemberTypeWithBase(DC->getParentModule(), typeDecl, baseObjTy); + // If the member type is a constraint, e.g. because the + // reference is to a typealias with an underlying protocol + // or composition type, the member reference has existential + // type. + if (memberTy->isConstraintType()) + memberTy = ExistentialType::get(memberTy); + checkNestedTypeConstraints(*this, memberTy, locator); // Convert any placeholders and open any generics. @@ -1995,8 +2002,12 @@ ConstraintSystem::getTypeOfMemberReference( if (t->isEqual(selfTy)) return baseObjTy; if (auto *metatypeTy = t->getAs<MetatypeType>()) - if (metatypeTy->getInstanceType()->isEqual(selfTy)) - return ExistentialMetatypeType::get(baseObjTy); + if (metatypeTy->getInstanceType()->isEqual(selfTy)) { + auto constraint = baseObjTy; + if (auto existential = baseObjTy->getAs<ExistentialType>()) + constraint = existential->getConstraintType(); + return ExistentialMetatypeType::get(constraint); + } return t; }); } @@ -2146,7 +2157,8 @@ Type ConstraintSystem::getEffectiveOverloadType(ConstraintLocator *locator, } else if (isa<AbstractFunctionDecl>(decl) || isa<EnumElementDecl>(decl)) { if (decl->isInstanceMember() && (!overload.getBaseType() || - !overload.getBaseType()->getAnyNominal())) + (!overload.getBaseType()->getAnyNominal() && + !overload.getBaseType()->is<ExistentialType>()))) return Type(); // Cope with 'Self' returns. @@ -2506,14 +2518,16 @@ FunctionType::ExtInfo ClosureEffectsRequest::evaluate( // Okay, now it should be safe to coerce the pattern. // Pull the top-level pattern back out. pattern = LabelItem.getPattern(); - Type exnType = DC->getASTContext().getErrorDecl()->getDeclaredInterfaceType(); - if (!exnType) + auto &ctx = DC->getASTContext(); + if (!ctx.getErrorDecl()) return false; + auto contextualPattern = ContextualPattern::forRawPattern(pattern, DC); pattern = TypeChecker::coercePatternToType( - contextualPattern, exnType, TypeResolverContext::InExpression); + contextualPattern, ctx.getErrorExistentialType(), + TypeResolverContext::InExpression); if (!pattern) return false; diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp index a3b9730280f7b..3273cb60d04da 100644 --- a/lib/Sema/DerivedConformanceCodable.cpp +++ b/lib/Sema/DerivedConformanceCodable.cpp @@ -1211,7 +1211,7 @@ static FuncDecl *deriveEncodable_encode(DerivedConformance &derived) { // output: () // Create from the inside out: - auto encoderType = C.getEncoderType(); + auto encoderType = ExistentialType::get(C.getEncoderType()); auto returnType = TupleType::getEmpty(C); // Params: (Encoder) @@ -1802,7 +1802,7 @@ static ValueDecl *deriveDecodable_init(DerivedConformance &derived) { // Compute from the inside out: // Params: (Decoder) - auto decoderType = C.getDecoderType(); + auto decoderType = ExistentialType::get(C.getDecoderType()); auto *decoderParamDecl = new (C) ParamDecl( SourceLoc(), SourceLoc(), C.Id_from, SourceLoc(), C.Id_decoder, conformanceDC); diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index 5b9d1da40891a..e1b1d6813f512 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -783,7 +783,12 @@ class AccessControlChecker : public AccessControlCheckerBase, Type()); } - auto declKindForType = [](Type type) { + auto declKindForType = [](Type type) -> DescriptiveDeclKind { + // If this is an existential type, use the decl kind of + // its constraint type. + if (auto existential = type->getAs<ExistentialType>()) + type = existential->getConstraintType(); + if (isa<TypeAliasType>(type.getPointer())) return DescriptiveDeclKind::TypeAlias; else if (auto nominal = type->getAnyNominal()) diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 77ef0a640a3dd..e310765773040 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -3000,8 +3000,10 @@ void AttributeChecker::visitImplementsAttr(ImplementsAttr *attr) { Type T = attr->getProtocolType(); if (!T && attr->getProtocolTypeRepr()) { + auto context = TypeResolverContext::GenericRequirement; T = TypeResolution::resolveContextualType(attr->getProtocolTypeRepr(), DC, - None, /*unboundTyOpener*/ nullptr, + TypeResolutionOptions(context), + /*unboundTyOpener*/ nullptr, /*placeholderHandler*/ nullptr); } diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 1224ebd7bce03..8d0aa0d38d5ae 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -1712,13 +1712,16 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType, // } // } // + auto constraint = fromType; + if (auto existential = constraint->getAs<ExistentialType>()) + constraint = existential->getConstraintType(); if (auto *protocolDecl = - dyn_cast_or_null<ProtocolDecl>(fromType->getAnyNominal())) { + dyn_cast_or_null<ProtocolDecl>(constraint->getAnyNominal())) { if (!couldDynamicallyConformToProtocol(toType, protocolDecl, module)) { return failed(); } } else if (auto protocolComposition = - fromType->getAs<ProtocolCompositionType>()) { + constraint->getAs<ProtocolCompositionType>()) { if (llvm::any_of(protocolComposition->getMembers(), [&](Type protocolType) { if (auto protocolDecl = dyn_cast_or_null<ProtocolDecl>( @@ -1973,6 +1976,12 @@ static bool checkForDynamicAttribute(CanType ty, } } + // If this is an existential type, check if its constraint type + // has the attribute. + if (auto existential = ty->getAs<ExistentialType>()) { + return hasAttribute(existential->getConstraintType()); + } + // If this is a protocol composition, check if any of its members have the // attribute. if (auto protocolComp = dyn_cast<ProtocolCompositionType>(ty)) { diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 08eba2bf58742..29afff0f8897a 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1899,6 +1899,14 @@ bool swift::isMemberOperator(FuncDecl *decl, Type type) { } if (isProtocol) { + // FIXME: Source compatibility hack for Swift 5. The compiler + // accepts member operators on protocols with existential + // type arguments. We should consider banning this in Swift 6. + if (auto existential = paramType->getAs<ExistentialType>()) { + if (selfNominal == existential->getConstraintType()->getAnyNominal()) + return true; + } + // For a protocol, is it the 'Self' type parameter? if (auto genericParam = paramType->getAs<GenericTypeParamType>()) if (genericParam->isEqual(DC->getSelfInterfaceType())) diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp index e6b7906a80a04..817d30eac58f6 100644 --- a/lib/Sema/TypeCheckDeclObjC.cpp +++ b/lib/Sema/TypeCheckDeclObjC.cpp @@ -806,7 +806,8 @@ bool swift::isRepresentableInObjC( Optional<unsigned> completionHandlerErrorParamIndex; if (FD->hasThrows()) { completionHandlerErrorParamIndex = completionHandlerParams.size(); - addCompletionHandlerParam(OptionalType::get(ctx.getExceptionType())); + auto errorType = ctx.getErrorExistentialType(); + addCompletionHandlerParam(OptionalType::get(errorType)); } Type completionHandlerType = FunctionType::get( diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 86cc1c175c58b..28ef660793272 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -4783,6 +4783,19 @@ ResolveWitnessResult ConformanceChecker::resolveTypeWitnessViaLookup( auto memberType = TypeChecker::substMemberTypeWithBase(DC->getParentModule(), typeDecl, Adoptee); + // Type witnesses that resolve to constraint types are always + // existential types. This can only happen when the type witness + // is explicitly written with a type alias. The type alias itself + // is still a constraint type because it can be used as both a + // type witness and as a generic constraint. + // + // With SE-0335, using a type alias as both a type witness and a generic + // constraint will be disallowed in Swift 6, because existential types + // must be explicit, and a generic constraint isn't a valid type witness. + if (memberType->isConstraintType()) { + memberType = ExistentialType::get(memberType); + } + if (!viableTypes.insert(memberType->getCanonicalType()).second) continue; @@ -5256,8 +5269,11 @@ void swift::diagnoseConformanceFailure(Type T, TypeChecker::containsProtocol(T, Proto, DC->getParentModule())) { if (!T->isObjCExistentialType()) { + Type constraintType = T; + if (auto existential = T->getAs<ExistentialType>()) + constraintType = existential->getConstraintType(); diags.diagnose(ComplainLoc, diag::type_cannot_conform, true, - T, T->isEqual(Proto->getDeclaredInterfaceType()), + T, constraintType->isEqual(Proto->getDeclaredInterfaceType()), Proto->getDeclaredInterfaceType()); diags.diagnose(ComplainLoc, diag::only_concrete_types_conform_to_protocols); @@ -5390,7 +5406,10 @@ TypeChecker::containsProtocol(Type T, ProtocolDecl *Proto, ModuleDecl *M, if (T->isExistentialType()) { // Handle the special case of the Error protocol, which self-conforms // *and* has a witness table. - if (T->isEqual(Proto->getDeclaredInterfaceType()) && + auto constraint = T; + if (auto existential = T->getAs<ExistentialType>()) + constraint = existential->getConstraintType(); + if (constraint->isEqual(Proto->getDeclaredInterfaceType()) && Proto->requiresSelfConformanceWitnessTable()) { auto &ctx = M->getASTContext(); return ProtocolConformanceRef(ctx.getSelfConformance(Proto)); diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 3b7ba396b179e..533eec0efd238 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -855,10 +855,11 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> { // Coerce the operand to the exception type. auto E = TS->getSubExpr(); - Type exnType = getASTContext().getErrorDecl()->getDeclaredInterfaceType(); - if (!exnType) return TS; + if (!getASTContext().getErrorDecl()) + return TS; - TypeChecker::typeCheckExpression(E, DC, {exnType, CTP_ThrowStmt}); + Type errorType = getASTContext().getErrorExistentialType(); + TypeChecker::typeCheckExpression(E, DC, {errorType, CTP_ThrowStmt}); TS->setSubExpr(E); return TS; @@ -1205,7 +1206,7 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> { auto catches = S->getCatches(); checkSiblingCaseStmts(catches.begin(), catches.end(), CaseParentKind::DoCatch, limitExhaustivityChecks, - getASTContext().getExceptionType()); + getASTContext().getErrorExistentialType()); return S; } diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 2e847303218f5..d96094b47393f 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -2274,7 +2274,13 @@ TypeResolver::resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr, Optional<MetatypeRepresentation> storedRepr; // The instance type is not a SIL type. auto instanceOptions = options; - instanceOptions.setContext(None); + TypeResolverContext context = TypeResolverContext::None; + if (isa<MetatypeTypeRepr>(repr)) { + context = TypeResolverContext::MetatypeBase; + } else if (isa<ProtocolTypeRepr>(repr)) { + context = TypeResolverContext::ProtocolMetatypeBase; + } + instanceOptions.setContext(context); instanceOptions -= TypeResolutionFlags::SILType; auto instanceTy = resolveType(base, instanceOptions); @@ -3166,7 +3172,8 @@ NeverNullType TypeResolver::resolveSILFunctionType( ProtocolConformanceRef witnessMethodConformance; if (witnessMethodProtocol) { - auto resolved = resolveType(witnessMethodProtocol, options); + auto resolved = resolveType(witnessMethodProtocol, + options.withContext(TypeResolverContext::GenericRequirement)); if (resolved->hasError()) return resolved; @@ -3442,11 +3449,7 @@ TypeResolver::resolveIdentifierType(IdentTypeRepr *IdType, return ErrorType::get(getASTContext()); } - // FIXME: Don't use ExistentialType for AnyObject for now. - bool isConstraintType = (result->is<ProtocolType>() && - !result->isAnyObject()); - if (isConstraintType && - getASTContext().LangOpts.EnableExplicitExistentialTypes && + if (result->isConstraintType() && options.isConstraintImplicitExistential()) { return ExistentialType::get(result); } @@ -3807,7 +3810,7 @@ TypeResolver::resolveCompositionType(CompositionTypeRepr *repr, continue; } - if (ty->isExistentialType()) { + if (ty->isConstraintType()) { auto layout = ty->getExistentialLayout(); if (auto superclass = layout.explicitSuperclass) if (checkSuperclass(tyR->getStartLoc(), superclass)) @@ -3835,10 +3838,8 @@ TypeResolver::resolveCompositionType(CompositionTypeRepr *repr, auto composition = ProtocolCompositionType::get(getASTContext(), Members, /*HasExplicitAnyObject=*/false); - if (getASTContext().LangOpts.EnableExplicitExistentialTypes && - options.isConstraintImplicitExistential() && - !composition->isAny()) { - composition = ExistentialType::get(composition); + if (options.isConstraintImplicitExistential()) { + return ExistentialType::get(composition); } return composition; } @@ -3861,14 +3862,6 @@ TypeResolver::resolveExistentialType(ExistentialTypeRepr *repr, return constraintType; } - // Warn about `any Any` and `any AnyObject`. - if (constraintType->isAny() || constraintType->isAnyObject()) { - diagnose(repr->getLoc(), diag::unnecessary_any, - constraintType) - .fixItRemove({anyStart, anyEnd}); - return constraintType; - } - return ExistentialType::get(constraintType); } @@ -4085,7 +4078,8 @@ class ExistentialTypeVisitor if (proto->existentialRequiresAny()) { Ctx.Diags.diagnose(comp->getNameLoc(), diag::existential_requires_any, - proto->getName()); + proto->getName()) + .limitBehavior(DiagnosticBehavior::Warning); } } else if (auto *alias = dyn_cast_or_null<TypeAliasDecl>(comp->getBoundDecl())) { auto type = Type(alias->getDeclaredInterfaceType()->getDesugaredType()); @@ -4101,7 +4095,8 @@ class ExistentialTypeVisitor Ctx.Diags.diagnose(comp->getNameLoc(), diag::existential_requires_any, - protoDecl->getName()); + protoDecl->getName()) + .limitBehavior(DiagnosticBehavior::Warning); } } return false; diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 4e6678f7c7821..96593dd81be82 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -6117,6 +6117,7 @@ Expected<Type> TypeDeserializer::getTypeCheckedImpl() { CASE(SequenceArchetype) CASE(GenericTypeParam) CASE(ProtocolComposition) + CASE(Existential) CASE(DependentMember) CASE(BoundGeneric) CASE(SILBlockStorage) diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 7af4335eb0faa..1ea761faf1e58 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -56,7 +56,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 655; // dealloc_stack_ref +const uint16_t SWIFTMODULE_VERSION_MINOR = 656; // enable explicit existentials /// A standard hash seed used for all string hashes in a serialized module. /// diff --git a/stdlib/public/Reflection/TypeRefBuilder.cpp b/stdlib/public/Reflection/TypeRefBuilder.cpp index a85eab6dfb3b1..d7a88e95136a3 100644 --- a/stdlib/public/Reflection/TypeRefBuilder.cpp +++ b/stdlib/public/Reflection/TypeRefBuilder.cpp @@ -30,8 +30,10 @@ using namespace swift; using namespace reflection; -TypeRefBuilder::BuiltType TypeRefBuilder::decodeMangledType(Node *node) { - return swift::Demangle::decodeMangledType(*this, node).getType(); +TypeRefBuilder::BuiltType +TypeRefBuilder::decodeMangledType(Node *node, bool forRequirement) { + return swift::Demangle::decodeMangledType(*this, node, forRequirement) + .getType(); } RemoteRef<char> TypeRefBuilder::readTypeRef(uint64_t remoteAddr) { diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp index ebcfe07948695..d0748a1a3aefb 100644 --- a/stdlib/public/runtime/MetadataLookup.cpp +++ b/stdlib/public/runtime/MetadataLookup.cpp @@ -1314,8 +1314,10 @@ class DecodedMetadataBuilder { using BuiltTypeDecl = const ContextDescriptor *; using BuiltProtocolDecl = ProtocolDescriptorRef; - BuiltType decodeMangledType(NodePointer node) { - return Demangle::decodeMangledType(*this, node).getType(); + BuiltType decodeMangledType(NodePointer node, + bool forRequirement = true) { + return Demangle::decodeMangledType(*this, node, forRequirement) + .getType(); } Demangle::NodeFactory &getNodeFactory() { return demangler; } @@ -1483,7 +1485,8 @@ class DecodedMetadataBuilder { TypeLookupErrorOr<BuiltType> createProtocolCompositionType(llvm::ArrayRef<BuiltProtocolDecl> protocols, - BuiltType superclass, bool isClassBound) const { + BuiltType superclass, bool isClassBound, + bool forRequirement = true) const { // Determine whether we have a class bound. ProtocolClassConstraint classConstraint = ProtocolClassConstraint::Any; if (isClassBound || superclass) { diff --git a/test/ClangImporter/objc_bridging_generics.swift b/test/ClangImporter/objc_bridging_generics.swift index 8de2c4b6be402..b819a82433f2e 100644 --- a/test/ClangImporter/objc_bridging_generics.swift +++ b/test/ClangImporter/objc_bridging_generics.swift @@ -1,4 +1,5 @@ // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -parse-as-library -verify -swift-version 4 -I %S/Inputs/custom-modules %s +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -parse-as-library -enable-explicit-existential-types -verify -swift-version 4 -I %S/Inputs/custom-modules %s // REQUIRES: objc_interop diff --git a/test/Constraints/common_type_objc.swift b/test/Constraints/common_type_objc.swift index 35a7239ae08cf..94596747ae77b 100644 --- a/test/Constraints/common_type_objc.swift +++ b/test/Constraints/common_type_objc.swift @@ -1,6 +1,9 @@ // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify %s -debug-constraints 2>%t.err // RUN: %FileCheck %s < %t.err +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify -enable-explicit-existential-types %s -debug-constraints 2>%t.err +// RUN: %FileCheck %s < %t.err + // REQUIRES: objc_interop import Foundation diff --git a/test/Constraints/openExistential.swift b/test/Constraints/openExistential.swift index a50d1ef26daea..48dcfb383df5b 100644 --- a/test/Constraints/openExistential.swift +++ b/test/Constraints/openExistential.swift @@ -1,4 +1,5 @@ // RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -enable-explicit-existential-types protocol P { } diff --git a/test/Constraints/protocols.swift b/test/Constraints/protocols.swift index f82e45f3ee30b..ec390422e8dcd 100644 --- a/test/Constraints/protocols.swift +++ b/test/Constraints/protocols.swift @@ -1,4 +1,5 @@ // RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -enable-explicit-existential-types protocol Fooable { func foo() } protocol Barable { func bar() } diff --git a/test/Generics/function_defs.swift b/test/Generics/function_defs.swift index 8b5d8499ebfa3..04f2f8e7f9a79 100644 --- a/test/Generics/function_defs.swift +++ b/test/Generics/function_defs.swift @@ -34,7 +34,7 @@ func min<T : MethodLessComparable>(_ x: T, y: T) -> T { //===----------------------------------------------------------------------===// func existential<T : EqualComparable, U : EqualComparable>(_ t1: T, t2: T, u: U) { - var eqComp : EqualComparable = t1 // Ok + var eqComp : EqualComparable = t1 // expected-warning {{protocol 'EqualComparable' as a type must be explicitly marked as 'any'}} eqComp = u if t1.isEqual(eqComp) {} // expected-error{{cannot convert value of type 'EqualComparable' to expected argument type 'T'}} if eqComp.isEqual(t2) {} // expected-error{{member 'isEqual' cannot be used on value of protocol type 'EqualComparable'; use a generic constraint instead}} @@ -49,11 +49,11 @@ func otherExistential<T : EqualComparable>(_ t1: T) { otherEqComp = t1 // expected-error{{value of type 'T' does not conform to 'OtherEqualComparable' in assignment}} _ = otherEqComp - var otherEqComp2 : OtherEqualComparable // Ok + var otherEqComp2 : any 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}} + _ = t1 as any EqualComparable & OtherEqualComparable // expected-error{{value of type 'T' does not conform to 'EqualComparable & OtherEqualComparable' in coercion}} } //===----------------------------------------------------------------------===// diff --git a/test/SILGen/protocol_with_superclass.swift b/test/SILGen/protocol_with_superclass.swift index 8f3c86bc2f9bc..e389e5c9a59a5 100644 --- a/test/SILGen/protocol_with_superclass.swift +++ b/test/SILGen/protocol_with_superclass.swift @@ -1,6 +1,9 @@ // RUN: %target-swift-emit-silgen %s | %FileCheck %s // RUN: %target-swift-frontend -emit-ir %s +// RUN: %target-swift-emit-silgen -enable-explicit-existential-types %s | %FileCheck %s +// RUN: %target-swift-frontend -emit-ir -enable-explicit-existential-types %s + // Protocols with superclass-constrained Self. class Concrete { diff --git a/test/SILGen/subclass_existentials.swift b/test/SILGen/subclass_existentials.swift index 7141a054bfe8b..e0d1de9bf6f27 100644 --- a/test/SILGen/subclass_existentials.swift +++ b/test/SILGen/subclass_existentials.swift @@ -2,6 +2,9 @@ // RUN: %target-swift-emit-silgen -module-name subclass_existentials -Xllvm -sil-full-demangle -parse-as-library -primary-file %s -verify | %FileCheck %s // RUN: %target-swift-emit-ir -module-name subclass_existentials -parse-as-library -primary-file %s +// RUN: %target-swift-emit-silgen -module-name subclass_existentials -Xllvm -sil-full-demangle -parse-as-library -enable-explicit-existential-types -primary-file %s -verify | %FileCheck %s +// RUN: %target-swift-emit-ir -module-name subclass_existentials -parse-as-library -enable-explicit-existential-types -primary-file %s + // Note: we pass -verify above to ensure there are no spurious // compiler warnings relating to casts. diff --git a/test/Sema/type_join.swift b/test/Sema/type_join.swift index 3de393ed929e4..8b856bb2f9075 100644 --- a/test/Sema/type_join.swift +++ b/test/Sema/type_join.swift @@ -1,4 +1,5 @@ // RUN: %target-typecheck-verify-swift -parse-stdlib +// RUN: %target-typecheck-verify-swift -parse-stdlib -enable-explicit-existential-types import Swift diff --git a/test/decl/nested/protocol.swift b/test/decl/nested/protocol.swift index f6f261bfdd35d..2bda50bf6ee46 100644 --- a/test/decl/nested/protocol.swift +++ b/test/decl/nested/protocol.swift @@ -31,7 +31,7 @@ protocol OuterProtocol { struct ConformsToOuterProtocol : OuterProtocol { typealias Hen = Int - func f() { let _ = InnerProtocol.self } // Ok + func f() { let _ = InnerProtocol.self } // expected-warning {{protocol 'InnerProtocol' as a type must be explicitly marked as 'any'}} } protocol Racoon { diff --git a/test/decl/protocol/conforms/inherited.swift b/test/decl/protocol/conforms/inherited.swift index 33e50e5ee418b..8b54508922117 100644 --- a/test/decl/protocol/conforms/inherited.swift +++ b/test/decl/protocol/conforms/inherited.swift @@ -167,13 +167,13 @@ class B : A { } func testB(_ b: B) { - var _: P1 = b - var _: P4 = b + var _: P1 = b // expected-warning {{protocol 'P1' as a type must be explicitly marked as 'any'}} + var _: P4 = b // expected-warning {{protocol 'P4' as a type must be explicitly marked as 'any'}} var _: P5 = b var _: P6 = b - var _: P7 = b + var _: P7 = b // expected-warning {{protocol 'P7' as a type must be explicitly marked as 'any'}} var _: P8 = b - var _: P9 = b + var _: P9 = b // expected-warning {{protocol 'P9' as a type must be explicitly marked as 'any'}} } // Class A5 conforms to P5 in an inheritable manner. diff --git a/test/decl/protocol/protocols.swift b/test/decl/protocol/protocols.swift index 89a12f2f7cf1f..c002d33a1f6e1 100644 --- a/test/decl/protocol/protocols.swift +++ b/test/decl/protocol/protocols.swift @@ -119,7 +119,7 @@ struct Circle { func testCircular(_ circle: Circle) { // FIXME: It would be nice if this failure were suppressed because the protocols // have circular definitions. - _ = circle as CircleStart // expected-error{{value of type 'Circle' does not conform to 'CircleStart' in coercion}} + _ = circle as any CircleStart // expected-error{{value of type 'Circle' does not conform to 'CircleStart' in coercion}} } // <rdar://problem/14750346> @@ -439,17 +439,17 @@ func g<T : C2>(_ x : T) { class C3 : P1 {} // expected-error{{type 'C3' does not conform to protocol 'P1'}} func h<T : C3>(_ x : T) { - _ = x as P1 + _ = x as any P1 } func i<T : C3>(_ x : T?) -> Bool { - return x is P1 + return x is any P1 // expected-warning@-1 {{checking a value with optional type 'T?' against type 'P1' succeeds whenever the value is non-nil; did you mean to use '!= nil'?}} } func j(_ x : C1) -> Bool { - return x is P1 + return x is P1 // expected-warning {{protocol 'P1' as a type must be explicitly marked as 'any'}} } func k(_ x : C1?) -> Bool { - return x is P1 + return x is any 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 index 05d6410ead2fa..33fac5d434d45 100644 --- a/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift +++ b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift @@ -57,7 +57,7 @@ protocol P1 { func invariantSelf7(_: (G<Self>) -> Void) func invariantSelf8(_: G<(Self) -> Void>) func invariantSelf9(_: G<() -> Self>) - func invariantSelf10(_: P1 & C<Self>) + func invariantSelf10(_: any P1 & C<Self>) func invariantSelf11() -> G<Self>.InnerG<Void> func invariantAssoc1(_: inout Q) func invariantAssoc2(_: (inout Q) -> Void) @@ -68,7 +68,7 @@ protocol P1 { func invariantAssoc7(_: (G<Q>) -> Void) func invariantAssoc8(_: G<(Q) -> Void>) func invariantAssoc9(_: G<() -> Q>) - func invariantAssoc10(_: P1 & C<Q>) + func invariantAssoc10(_: any P1 & C<Q>) func invariantAssoc11() -> G<Q>.InnerG<Void> // Properties @@ -117,7 +117,7 @@ protocol P1 { var invariantSelfProp7: ((G<Self>) -> Void) -> Void { get } var invariantSelfProp8: (G<(Self) -> Void>) -> Void { get } var invariantSelfProp9: (G<() -> Self>) -> Void { get } - var invariantSelfProp10: (P1 & C<Self>) -> Void { get } + var invariantSelfProp10: (any P1 & C<Self>) -> Void { get } var invariantSelfProp11: G<Self>.InnerG<Void> { get } var invariantAssocProp1: (inout Q) -> Void { get } var invariantAssocProp2: ((inout Q) -> Void) -> Void { get } @@ -128,7 +128,7 @@ protocol P1 { var invariantAssocProp7: ((G<Q>) -> Void) { get } var invariantAssocProp8: (G<(Q) -> Void>) { get } var invariantAssocProp9: (G<() -> Q>) -> Void { get } - var invariantAssocProp10: (P1 & C<Q>) -> Void { get } + var invariantAssocProp10: (any P1 & C<Q>) -> Void { get } var invariantAssocProp11: G<Q>.InnerG<Void> { get } // Subscripts @@ -172,7 +172,7 @@ protocol P1 { subscript(invariantSelfSubscript4 _: (G<Self>) -> Void) -> Void { get } subscript(invariantSelfSubscript5 _: G<(Self) -> Void>) -> Void { get } subscript(invariantSelfSubscript6 _: G<() -> Self>) -> Void { get } - subscript(invariantSelfSubscript7 _: P1 & C<Self>) -> Void { get } + subscript(invariantSelfSubscript7 _: any P1 & C<Self>) -> Void { get } subscript(invariantSelfSubscript8 _: Void) -> G<Self>.InnerG<Void> { get } subscript(invariantAssocSubscript1 _: G<Q>) -> Void { get } subscript(invariantAssocSubscript2 _: Void) -> G<Q> { get } @@ -180,7 +180,7 @@ protocol P1 { subscript(invariantAssocSubscript4 _: (G<Q>) -> Void) -> Void { get } subscript(invariantAssocSubscript5 _: G<(Q) -> Void>) -> Void { get } subscript(invariantAssocSubscript6 _: G<() -> Q>) -> Void { get } - subscript(invariantAssocSubscript7 _: P1 & C<Q>) -> Void { get } + subscript(invariantAssocSubscript7 _: any P1 & C<Q>) -> Void { get } subscript(invariantAssocSubscript8 _: Void) -> G<Q>.InnerG<Void> { get } } @available(macOS 10.15, *) @@ -191,40 +191,40 @@ extension P1 { } do { - func testP1(arg: P1) { + func testP1(arg: any P1) { _ = arg.covariantSelfSimple() // ok - let _: P1 = arg.covariantSelfSimple() // ok + let _: any 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<P1>) in }, - { (x: Array<Array<P1>?>) in } + let _: [String : () -> (any P1, any P1)] = arg.covariantSelfComplex( + { (x: any P1) in }, + { (x: (any P1)?) in }, + { (x: Array<any P1>) in }, + { (x: Array<Array<any P1>?>) 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 + let _: any P1 = arg.covariantSelfPropSimple // ok _ = arg.covariantSelfPropComplex // ok let _: ( - _: (P1) -> Void, - _: (P1?) -> Void, - _: (Array<P1>) -> Void, - _: (Array<Array<P1>?>) -> Void - ) -> [String : () -> (P1, P1)] = arg.covariantSelfPropComplex // ok + _: (any P1) -> Void, + _: ((any P1)?) -> Void, + _: (Array<any P1>) -> Void, + _: (Array<Array<any P1>?>) -> Void + ) -> [String : () -> (any P1, any 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 + let _: any 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<P1>) in }, - { (x: Array<Array<P1>?>) in } + let _: [String : () -> (any P1, any P1)] = arg[ + covariantSelfSubscriptComplex: { (x: any P1) in }, + { (x: (any P1)?) in }, + { (x: Array<any P1>) in }, + { (x: Array<Array<any P1>?>) 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}} @@ -444,15 +444,15 @@ protocol P1_TypeMemberOnInstanceAndViceVersa { 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) { + func test(protoMeta: (any P1_TypeMemberOnInstanceAndViceVersa).Type, + existMeta: any P1_TypeMemberOnInstanceAndViceVersa.Type, + instance: any 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.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.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'}} @@ -481,7 +481,7 @@ protocol P2 { var prop: Self { get set } } -func takesP2(p2: P2) { +func takesP2(p2: any P2) { _ = p2[] // expected-error@-1{{member 'subscript' cannot be used on value of protocol type 'P2'; use a generic constraint instead}} _ = p2.prop @@ -500,7 +500,7 @@ protocol MiscTestsProto { subscript(intToInt _: Int) -> Int { get } } do { - func miscTests(_ arg: MiscTestsProto) { // ok + func miscTests(_ arg: any MiscTestsProto) { // ok arg.runce(5) do { @@ -515,7 +515,7 @@ do { _ = 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) { + func existentialSequence(_ e: any 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/recursive_requirement.swift b/test/decl/protocol/recursive_requirement.swift index c99dadbb6b4bd..eab9ac2f8687e 100644 --- a/test/decl/protocol/recursive_requirement.swift +++ b/test/decl/protocol/recursive_requirement.swift @@ -91,7 +91,7 @@ protocol AsExistentialB { } protocol AsExistentialAssocTypeA { - var delegate : AsExistentialAssocTypeB? { get } + var delegate : AsExistentialAssocTypeB? { get } // expected-warning {{protocol 'AsExistentialAssocTypeB' as a type must be explicitly marked as 'any'}} } protocol AsExistentialAssocTypeB { func aMethod(_ object : AsExistentialAssocTypeA) @@ -103,7 +103,7 @@ protocol AsExistentialAssocTypeAgainA { associatedtype Bar } protocol AsExistentialAssocTypeAgainB { - func aMethod(_ object : AsExistentialAssocTypeAgainA) + func aMethod(_ object : AsExistentialAssocTypeAgainA) // expected-warning {{protocol 'AsExistentialAssocTypeAgainA' as a type must be explicitly marked as 'any'}} } // SR-547 diff --git a/test/stmt/foreach.swift b/test/stmt/foreach.swift index e3c3d6a3cb6eb..f11f5ae72b7fc 100644 --- a/test/stmt/foreach.swift +++ b/test/stmt/foreach.swift @@ -176,7 +176,7 @@ func testOptionalSequence() { } // FIXME: Should this be allowed? -func testExistentialSequence(s: Sequence) { +func testExistentialSequence(s: any 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/explicit_existential.swift b/test/type/explicit_existential.swift index b19a802007686..38714635d6a86 100644 --- a/test/type/explicit_existential.swift +++ b/test/type/explicit_existential.swift @@ -149,9 +149,9 @@ func testInvalidAny() { let _: any ((S) -> Void) = generic // expected-error{{'any' has no effect on concrete type '(S) -> Void'}} } -func testRedundantAnyWarning() { - let _: any Any // expected-warning {{'any' is redundant on type 'Any'}} - let _: any AnyObject // expected-warning {{'any' is redundant on type 'AnyObject'}} +func anyAny() { + let _: any Any + let _: any AnyObject } protocol P1 {} @@ -162,3 +162,43 @@ func testMetatypes() { let _: any P1.Type = ConcreteComposition.self let _: any (P1 & P2).Type = ConcreteComposition.self } + +func generic<T: any P1>(_ t: T) {} // expected-error {{type 'T' constrained to non-protocol, non-class type 'any P1'}} + +protocol RawRepresentable { + associatedtype RawValue + var rawValue: RawValue { get } +} + +enum E1: RawRepresentable { + typealias RawValue = P1 + + var rawValue: P1 { + return ConcreteComposition() + } +} + +enum E2: RawRepresentable { + typealias RawValue = any P1 + + var rawValue: any P1 { + return ConcreteComposition() + } +} + +public protocol MyError {} + +extension MyError { + static func ~=(lhs: any Error, rhs: Self) -> Bool { + return true + } +} + +struct Wrapper { + typealias E = Error +} + +func typealiasMemberReferences(metatype: Wrapper.Type) { + let _: Wrapper.E.Protocol = metatype.E.self + let _: (any Wrapper.E).Type = metatype.E.self +} diff --git a/test/type/protocol_types.swift b/test/type/protocol_types.swift index d2d02dd612a3b..41df887c396d0 100644 --- a/test/type/protocol_types.swift +++ b/test/type/protocol_types.swift @@ -3,7 +3,7 @@ protocol HasSelfRequirements { func foo(_ x: Self) - func returnsOwnProtocol() -> HasSelfRequirements + func returnsOwnProtocol() -> HasSelfRequirements // expected-warning {{protocol 'HasSelfRequirements' as a type must be explicitly marked as 'any'}} } protocol Bar { // init() methods should not prevent use as an existential. @@ -36,10 +36,10 @@ func useCompoAsWhereRequirement<T>(_ x: T) where T: HasSelfRequirements & Bar {} func useCompoAliasAsWhereRequirement<T>(_ x: T) where T: Compo {} func useNestedCompoAliasAsWhereRequirement<T>(_ x: T) where T: CompoAssocType.Compo {} -func useAsType(_: HasSelfRequirements, - _: HasSelfRequirements & Bar, - _: Compo, - _: CompoAssocType.Compo) { } +func useAsType(_: any HasSelfRequirements, + _: any HasSelfRequirements & Bar, + _: any Compo, + _: any CompoAssocType.Compo) { } struct TypeRequirement<T: HasSelfRequirements> {} struct CompoTypeRequirement<T: HasSelfRequirements & Bar> {} @@ -74,7 +74,7 @@ do { func checkIt(_ js: Any) throws { switch js { - case let dbl as HasAssoc: + case let dbl as HasAssoc: // expected-warning {{protocol 'HasAssoc' as a type must be explicitly marked as 'any'}} throw MyError.bad(dbl) default: @@ -83,8 +83,8 @@ do { } } -func testHasAssoc(_ x: Any, _: HasAssoc) { - if let p = x as? HasAssoc { +func testHasAssoc(_ x: Any, _: HasAssoc) { // expected-warning {{protocol 'HasAssoc' as a type must be explicitly marked as 'any'}} + if let p = x as? any HasAssoc { p.foo() // don't crash here. } @@ -92,18 +92,18 @@ func testHasAssoc(_ x: Any, _: HasAssoc) { typealias Assoc = Int func foo() {} - func method() -> HasAssoc {} + func method() -> HasAssoc {} // expected-warning {{protocol 'HasAssoc' as a type must be explicitly marked as 'any'}} } } // SR-38 -var b: HasAssoc +var b: HasAssoc // expected-warning {{protocol 'HasAssoc' as a type must be explicitly marked as 'any'}} // Further generic constraint error testing - typealias used inside statements protocol P {} typealias MoreHasAssoc = HasAssoc & P func testHasMoreAssoc(_ x: Any) { - if let p = x as? MoreHasAssoc { + if let p = x as? any MoreHasAssoc { p.foo() // don't crash here. } } @@ -118,34 +118,34 @@ typealias X = Struct1<Pub & Bar> _ = Struct1<Pub & Bar>.self typealias AliasWhere<T> = T -where T : HasAssoc, T.Assoc == HasAssoc +where T : HasAssoc, T.Assoc == HasAssoc // expected-warning {{protocol 'HasAssoc' as a type must be explicitly marked as 'any'}} struct StructWhere<T> where T : HasAssoc, - T.Assoc == HasAssoc {} + T.Assoc == any HasAssoc {} -protocol ProtocolWhere where T == HasAssoc { +protocol ProtocolWhere where T == HasAssoc { // expected-warning {{protocol 'HasAssoc' as a type must be explicitly marked as 'any'}} associatedtype T associatedtype U : HasAssoc - where U.Assoc == HasAssoc + where U.Assoc == any HasAssoc } -extension HasAssoc where Assoc == HasAssoc {} +extension HasAssoc where Assoc == HasAssoc {} // expected-warning {{protocol 'HasAssoc' as a type must be explicitly marked as 'any'}} func FunctionWhere<T>(_: T) where T : HasAssoc, - T.Assoc == HasAssoc {} + T.Assoc == any HasAssoc {} struct SubscriptWhere { subscript<T>(_: T) -> Int where T : HasAssoc, - T.Assoc == HasAssoc { + T.Assoc == any HasAssoc { get {} set {} } } struct OuterGeneric<T> { - func contextuallyGenericMethod() where T == HasAssoc {} + func contextuallyGenericMethod() where T == any HasAssoc {} }