diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index 3abb4cfd00a36..0d6ab02ec0dbf 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -1258,13 +1258,16 @@ class ASTContext final { unsigned bumpGeneration() { return CurrentGeneration++; } /// Produce a "normal" conformance for a nominal type. + /// + /// For ordinary conformance lookups, use ModuleDecl::lookupConformance() + /// instead. NormalProtocolConformance * - getConformance(Type conformingType, - ProtocolDecl *protocol, - SourceLoc loc, - DeclContext *dc, - ProtocolConformanceState state, - bool isUnchecked); + getNormalConformance(Type conformingType, + ProtocolDecl *protocol, + SourceLoc loc, + DeclContext *dc, + ProtocolConformanceState state, + bool isUnchecked); /// Produce a self-conformance for the given protocol. SelfProtocolConformance * @@ -1273,8 +1276,6 @@ class ASTContext final { /// Produce the builtin conformance for some structural type to some protocol. BuiltinProtocolConformance * getBuiltinConformance(Type type, ProtocolDecl *protocol, - GenericSignature genericSig, - ArrayRef conditionalRequirements, BuiltinConformanceKind kind); /// A callback used to produce a diagnostic for an ill-formed protocol diff --git a/include/swift/AST/DiagnosticsCommon.def b/include/swift/AST/DiagnosticsCommon.def index fa8692e45d32f..0a362e7e523bb 100644 --- a/include/swift/AST/DiagnosticsCommon.def +++ b/include/swift/AST/DiagnosticsCommon.def @@ -228,13 +228,6 @@ ERROR(macro_experimental,none, ERROR(ambiguous_macro_reference,none, "ambiguous reference to macro %0", (DeclName)) -//------------------------------------------------------------------------------ -// MARK: tuple conformances -//------------------------------------------------------------------------------ -ERROR(experimental_tuple_extension,none, - "tuple extensions are experimental", - ()) - //------------------------------------------------------------------------------ // MARK: bridged diagnostics //------------------------------------------------------------------------------ diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 888cf1f95cf61..97106963c3283 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -2335,6 +2335,9 @@ NOTE(composition_in_extended_type_alternative,none, ERROR(extension_access_with_conformances,none, "%0 modifier cannot be used with extensions that declare " "protocol conformances", (DeclAttribute)) +ERROR(experimental_tuple_extension,none, + "tuple extensions are experimental", + ()) ERROR(extension_metatype,none, "cannot extend a metatype %0", (Type)) ERROR(extension_placeholder,none, diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h index 456b8b60a18e0..3ca1b282f38e7 100644 --- a/include/swift/AST/ProtocolConformance.h +++ b/include/swift/AST/ProtocolConformance.h @@ -1019,23 +1019,13 @@ enum class BuiltinConformanceKind { /// A builtin conformance appears when a non-nominal type has a /// conformance that is synthesized by the implementation. -class BuiltinProtocolConformance final : public RootProtocolConformance, - private llvm::TrailingObjects { +class BuiltinProtocolConformance final : public RootProtocolConformance { friend ASTContext; - friend TrailingObjects; ProtocolDecl *protocol; - GenericSignature genericSig; - size_t numConditionalRequirements : 31; - unsigned builtinConformanceKind : 1; - - size_t numTrailingObjects(OverloadToken) const { - return numConditionalRequirements; - } + unsigned builtinConformanceKind; BuiltinProtocolConformance(Type conformingType, ProtocolDecl *protocol, - GenericSignature genericSig, - ArrayRef conditionalRequirements, BuiltinConformanceKind kind); public: @@ -1044,16 +1034,14 @@ class BuiltinProtocolConformance final : public RootProtocolConformance, return protocol; } - /// Retrieve the generic signature that describes the type parameters used - /// within the conforming type. - GenericSignature getGenericSignature() const { - return genericSig; - } - BuiltinConformanceKind getBuiltinConformanceKind() const { return static_cast(builtinConformanceKind); } + GenericSignature getGenericSignature() const { + return GenericSignature(); + } + /// Whether this represents a "missing" conformance that should be diagnosed /// later. bool isMissing() const { @@ -1063,12 +1051,12 @@ class BuiltinProtocolConformance final : public RootProtocolConformance, /// Get any requirements that must be satisfied for this conformance to apply. llvm::Optional> getConditionalRequirementsIfAvailable() const { - return getConditionalRequirements(); + return ArrayRef(); } /// Get any requirements that must be satisfied for this conformance to apply. ArrayRef getConditionalRequirements() const { - return {getTrailingObjects(), numConditionalRequirements}; + return {}; } /// Get the declaration context that contains the nominal type declaration. diff --git a/include/swift/Demangling/DemangleNodes.def b/include/swift/Demangling/DemangleNodes.def index dad2653ad11d8..8e4db9850f88a 100644 --- a/include/swift/Demangling/DemangleNodes.def +++ b/include/swift/Demangling/DemangleNodes.def @@ -44,6 +44,7 @@ NODE(BoundGenericOtherNominalType) NODE(BoundGenericTypeAlias) NODE(BoundGenericFunction) NODE(BuiltinTypeName) +NODE(BuiltinTupleType) NODE(CFunctionPointer) NODE(ClangType) CONTEXT_NODE(Class) diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 1dbb19ca78a9c..e2ccf9533ed3b 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2638,12 +2638,12 @@ void ASTContext::setExternalSourceLocs(const Decl *D, } NormalProtocolConformance * -ASTContext::getConformance(Type conformingType, - ProtocolDecl *protocol, - SourceLoc loc, - DeclContext *dc, - ProtocolConformanceState state, - bool isUnchecked) { +ASTContext::getNormalConformance(Type conformingType, + ProtocolDecl *protocol, + SourceLoc loc, + DeclContext *dc, + ProtocolConformanceState state, + bool isUnchecked) { assert(dc->isTypeContext()); llvm::FoldingSetNodeID id; @@ -2681,23 +2681,15 @@ ASTContext::getSelfConformance(ProtocolDecl *protocol) { /// Produce the builtin conformance for some non-nominal to some protocol. BuiltinProtocolConformance * -ASTContext::getBuiltinConformance( - Type type, ProtocolDecl *protocol, - GenericSignature genericSig, - ArrayRef conditionalRequirements, - BuiltinConformanceKind kind -) { +ASTContext::getBuiltinConformance(Type type, ProtocolDecl *protocol, + BuiltinConformanceKind kind) { auto key = std::make_pair(type, protocol); AllocationArena arena = getArena(type->getRecursiveProperties()); auto &builtinConformances = getImpl().getArena(arena).BuiltinConformances; auto &entry = builtinConformances[key]; if (!entry) { - auto size = BuiltinProtocolConformance:: - totalSizeToAlloc(conditionalRequirements.size()); - auto mem = this->Allocate(size, alignof(BuiltinProtocolConformance), arena); - entry = new (mem) BuiltinProtocolConformance( - type, protocol, genericSig, conditionalRequirements, kind); + entry = new (*this) BuiltinProtocolConformance(type, protocol, kind); } return entry; } @@ -3726,7 +3718,9 @@ BoundGenericType *BoundGenericType::get(NominalTypeDecl *TheDecl, } NominalType *NominalType::get(NominalTypeDecl *D, Type Parent, const ASTContext &C) { - assert((isa(D) || !D->getGenericParams()) && + assert((isa(D) || + isa(D) || + !D->getGenericParams()) && "must be a non-generic type decl"); assert((!Parent || Parent->is() || Parent->is() || @@ -3742,6 +3736,8 @@ NominalType *NominalType::get(NominalTypeDecl *D, Type Parent, const ASTContext return ClassType::get(cast(D), Parent, C); case DeclKind::Protocol: { return ProtocolType::get(cast(D), Parent, C); + case DeclKind::BuiltinTuple: + return BuiltinTupleType::get(cast(D), Parent, C); } default: @@ -6292,10 +6288,44 @@ BuiltinTupleDecl *ASTContext::getBuiltinTupleDecl() { if (result) return result; - result = new (*this) BuiltinTupleDecl(Id_TheTupleType, - TheBuiltinModule->getFiles()[0]); + auto *dc = TheBuiltinModule->getFiles()[0]; + + result = new (*this) BuiltinTupleDecl(Id_TheTupleType, dc); result->setAccess(AccessLevel::Public); + // Cook up conditional conformances to Sendable and Copyable. + auto buildFakeExtension = [&](ProtocolDecl *proto) { + auto protoTy = proto->getDeclaredInterfaceType(); + + // extension Builtin.TheTupleType: P { ... } + SmallVector inherited; + inherited.emplace_back(TypeLoc::withoutLoc(protoTy)); + auto *ext = ExtensionDecl::create(*this, SourceLoc(), nullptr, + AllocateCopy(inherited), + dc, nullptr); + + // + auto genericSig = result->getGenericSignature(); + auto params = genericSig.getGenericParams(); + assert(params.size() == 1); + Requirement req(RequirementKind::Conformance, params[0], protoTy); + genericSig = GenericSignature::get(params, req); + ext->setGenericSignature(genericSig); + + // Bind the extension. + evaluator.cacheOutput(ExtendedTypeRequest{ext}, + result->getDeclaredInterfaceType()); + ext->setExtendedNominal(result); + + result->addExtension(ext); + }; + + if (auto *proto = getProtocol(KnownProtocolKind::Sendable)) + buildFakeExtension(proto); + + if (auto *proto = getProtocol(KnownProtocolKind::Copyable)) + buildFakeExtension(proto); + return result; } diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index 0083ded9c0d37..778093238bb92 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -2583,6 +2583,11 @@ void ASTMangler::appendSymbolicReference(SymbolicReferent referent) { } void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) { + auto *nominal = dyn_cast(decl); + + if (nominal && isa(nominal)) + return appendOperator("BT"); + // Check for certain standard types. if (tryAppendStandardSubstitution(decl)) return; @@ -2592,8 +2597,6 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) { appendOpaqueDeclName(opaque); return; } - - auto *nominal = dyn_cast(decl); // For generic types, this uses the unbound type. if (nominal) { @@ -2612,9 +2615,6 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) { return; } - if (nominal && isa(nominal)) - return appendOperator("BT"); - appendContextOf(decl); // Always use Clang names for imported Clang declarations, unless they don't diff --git a/lib/AST/ConformanceLookupTable.cpp b/lib/AST/ConformanceLookupTable.cpp index 81b0d4e3849cb..d77b7a762ebe3 100644 --- a/lib/AST/ConformanceLookupTable.cpp +++ b/lib/AST/ConformanceLookupTable.cpp @@ -202,7 +202,8 @@ void ConformanceLookupTable::forEachInStage(ConformanceStage stage, for (auto conf : conformances) { protocols.push_back({conf->getProtocol(), SourceLoc(), SourceLoc()}); } - } else if (next->getParentSourceFile()) { + } else if (next->getParentSourceFile() || + next->getParentModule()->isBuiltinModule()) { bool anyObject = false; for (const auto &found : getDirectlyInheritedNominalTypeDecls(next, anyObject)) { @@ -418,8 +419,10 @@ void ConformanceLookupTable::loadAllConformances( ArrayRef conformances) { // If this declaration context came from source, there's nothing to // do here. - if (dc->getParentSourceFile()) + if (dc->getParentSourceFile() || + dc->getParentModule()->isBuiltinModule()) { return; + } // Add entries for each loaded conformance. for (auto conformance : conformances) { @@ -928,9 +931,9 @@ ConformanceLookupTable::getConformance(NominalTypeDecl *nominal, // Create or find the normal conformance. auto normalConf = - ctx.getConformance(conformingType, protocol, conformanceLoc, - conformingDC, ProtocolConformanceState::Incomplete, - entry->Source.getUncheckedLoc().isValid()); + ctx.getNormalConformance(conformingType, protocol, conformanceLoc, + conformingDC, ProtocolConformanceState::Incomplete, + entry->Source.getUncheckedLoc().isValid()); // Invalid code may cause the getConformance call below to loop, so break // the infinite recursion by setting this eagerly to shortcircuit with the // early return at the start of this function. diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 36bf89e37f5e0..7d6a59953c71e 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -1588,7 +1588,7 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) { // All existentials are Copyable. if (protocol->isSpecificProtocol(KnownProtocolKind::Copyable)) { return ProtocolConformanceRef( - ctx.getBuiltinConformance(type, protocol, GenericSignature(), {}, + ctx.getBuiltinConformance(type, protocol, BuiltinConformanceKind::Synthesized)); } @@ -1670,8 +1670,7 @@ ProtocolConformanceRef ProtocolConformanceRef::forMissingOrInvalid( if (shouldCreateMissingConformances(type, proto)) { return ProtocolConformanceRef( ctx.getBuiltinConformance( - type, proto, GenericSignature(), { }, - BuiltinConformanceKind::Missing)); + type, proto, BuiltinConformanceKind::Missing)); } return ProtocolConformanceRef::forInvalid(); @@ -1713,9 +1712,6 @@ static ProtocolConformanceRef getBuiltinTupleTypeConformance( ModuleDecl *module) { ASTContext &ctx = protocol->getASTContext(); - // This is the new code path. - // - // FIXME: Remove the Sendable stuff below. auto *tupleDecl = ctx.getBuiltinTupleDecl(); // Find the (unspecialized) conformance. @@ -1748,62 +1744,6 @@ static ProtocolConformanceRef getBuiltinTupleTypeConformance( return ProtocolConformanceRef(specialized); } - /// For some known protocols (KPs) like Sendable and Copyable, a tuple type - /// conforms to the protocol KP when all of their element types conform to KP. - if (protocol->isSpecificProtocol(KnownProtocolKind::Sendable) || - protocol->isSpecificProtocol(KnownProtocolKind::Copyable)) { - - // Create the pieces for a generic tuple type (T1, T2, ... TN) and a - // generic signature . - SmallVector genericParams; - SmallVector typeSubstitutions; - SmallVector genericElements; - SmallVector conditionalRequirements; - for (const auto &elt : tupleType->getElements()) { - auto genericParam = GenericTypeParamType::get(/*isParameterPack*/ false, 0, - genericParams.size(), ctx); - genericParams.push_back(genericParam); - typeSubstitutions.push_back(elt.getType()); - genericElements.push_back(elt.getWithType(genericParam)); - conditionalRequirements.push_back( - Requirement(RequirementKind::Conformance, genericParam, - protocol->getDeclaredType())); - } - - // If there were no generic parameters, just form the builtin conformance. - if (genericParams.empty()) { - return ProtocolConformanceRef( - ctx.getBuiltinConformance(type, protocol, GenericSignature(), { }, - BuiltinConformanceKind::Synthesized)); - } - - // Form a generic conformance of (T1, T2, ..., TN): KP with signature - // and conditional requirements T1: KP, - // T2: P, ..., TN: KP. - auto genericTupleType = TupleType::get(genericElements, ctx); - auto genericSig = GenericSignature::get( - genericParams, conditionalRequirements); - auto genericConformance = ctx.getBuiltinConformance( - genericTupleType, protocol, genericSig, conditionalRequirements, - BuiltinConformanceKind::Synthesized); - - // Compute the substitution map from the generic parameters of the - // generic conformance to actual types that were in the tuple type. - // Form a specialized conformance from that. - auto subMap = SubstitutionMap::get( - genericSig, [&](SubstitutableType *type) { - if (auto gp = dyn_cast(type)) { - if (gp->getDepth() == 0) - return typeSubstitutions[gp->getIndex()]; - } - - return Type(type); - }, - LookUpConformanceInModule(module)); - return ProtocolConformanceRef( - ctx.getSpecializedConformance(type, genericConformance, subMap)); - } - return ProtocolConformanceRef::forMissingOrInvalid(type, protocol); } @@ -1833,7 +1773,7 @@ static ProtocolConformanceRef getBuiltinFunctionTypeConformance( if (protocol->isSpecificProtocol(KnownProtocolKind::Sendable) && isSendableFunctionType(functionType)) { return ProtocolConformanceRef( - ctx.getBuiltinConformance(type, protocol, GenericSignature(), { }, + ctx.getBuiltinConformance(type, protocol, BuiltinConformanceKind::Synthesized)); } @@ -1841,7 +1781,7 @@ static ProtocolConformanceRef getBuiltinFunctionTypeConformance( // that they capture, so it's safe to copy functions, like classes. if (protocol->isSpecificProtocol(KnownProtocolKind::Copyable)) { return ProtocolConformanceRef( - ctx.getBuiltinConformance(type, protocol, GenericSignature(), {}, + ctx.getBuiltinConformance(type, protocol, BuiltinConformanceKind::Synthesized)); } @@ -1858,14 +1798,14 @@ static ProtocolConformanceRef getBuiltinMetaTypeTypeConformance( if (protocol->isSpecificProtocol(KnownProtocolKind::Copyable) && !metatypeType->getInstanceType()->isPureMoveOnly()) { return ProtocolConformanceRef( - ctx.getBuiltinConformance(type, protocol, GenericSignature(), { }, + ctx.getBuiltinConformance(type, protocol, BuiltinConformanceKind::Synthesized)); } // All metatypes are Sendable if (protocol->isSpecificProtocol(KnownProtocolKind::Sendable)) { return ProtocolConformanceRef( - ctx.getBuiltinConformance(type, protocol, GenericSignature(), { }, + ctx.getBuiltinConformance(type, protocol, BuiltinConformanceKind::Synthesized)); } @@ -1881,7 +1821,7 @@ static ProtocolConformanceRef getBuiltinBuiltinTypeConformance( protocol->isSpecificProtocol(KnownProtocolKind::Copyable)) { ASTContext &ctx = protocol->getASTContext(); return ProtocolConformanceRef( - ctx.getBuiltinConformance(type, protocol, GenericSignature(), { }, + ctx.getBuiltinConformance(type, protocol, BuiltinConformanceKind::Synthesized)); } @@ -1899,7 +1839,8 @@ static ProtocolConformanceRef getPackTypeConformance( auto patternConformance = (patternType->isTypeParameter() ? ProtocolConformanceRef(protocol) - : mod->lookupConformance(patternType, protocol)); + : mod->lookupConformance(patternType, protocol, + /*allowMissing=*/true)); patternConformances.push_back(patternConformance); continue; } @@ -1907,7 +1848,8 @@ static ProtocolConformanceRef getPackTypeConformance( auto patternConformance = (packElement->isTypeParameter() ? ProtocolConformanceRef(protocol) - : mod->lookupConformance(packElement, protocol)); + : mod->lookupConformance(packElement, protocol, + /*allowMissing=*/true)); patternConformances.push_back(patternConformance); } @@ -2007,17 +1949,6 @@ LookupConformanceInModuleRequest::evaluate( return getBuiltinBuiltinTypeConformance(type, builtinType, protocol); } - // Specific handling of Copyable and Sendable for pack expansions. - if (auto packExpansion = type->getAs()) { - if (protocol->isSpecificProtocol(KnownProtocolKind::Copyable) || - protocol->isSpecificProtocol(KnownProtocolKind::Sendable)) { - auto patternType = packExpansion->getPatternType(); - return (patternType->isTypeParameter() - ? ProtocolConformanceRef(protocol) - : mod->lookupConformance(patternType, protocol)); - } - } - auto nominal = type->getAnyNominal(); // If we don't have a nominal type, there are no conformances. diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index c520bb9d3db61..6090bbc9a7033 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -3190,12 +3190,6 @@ ExtendedNominalRequest::evaluate(Evaluator &evaluator, if (nominalTypes.empty()) return nullptr; - // Diagnose experimental tuple extensions. - if (isa(nominalTypes[0]) && - !ctx.LangOpts.hasFeature(Feature::TupleConformances)) { - ext->diagnose(diag::experimental_tuple_extension); - } - return nominalTypes[0]; } diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp index 10bb94836bfd8..014a5cfc39dfc 100644 --- a/lib/AST/ProtocolConformance.cpp +++ b/lib/AST/ProtocolConformance.cpp @@ -310,7 +310,7 @@ bool NormalProtocolConformance::isResilient() const { // FIXME: Looking at the type is not the right long-term solution. We need an // explicit mechanism for declaring conformances as 'fragile', or even // individual witnesses. - if (!getType()->getAnyNominal()->isResilient()) + if (!getDeclContext()->getSelfNominalTypeDecl()->isResilient()) return false; return getDeclContext()->getParentModule()->isResilient(); @@ -967,18 +967,11 @@ ProtocolConformance::subst(InFlightSubstitution &IFS) const { if (substType.getPointer() == origType.getPointer()) return const_cast(this); - SmallVector requirements; - for (auto req : getConditionalRequirements()) { - requirements.push_back(req.subst(IFS)); - } - auto kind = cast(this) ->getBuiltinConformanceKind(); return substType->getASTContext() - .getBuiltinConformance(substType, - getProtocol(), getGenericSignature(), - requirements, kind); + .getBuiltinConformance(substType, getProtocol(), kind); } case ProtocolConformanceKind::Self: return const_cast(this); @@ -1410,18 +1403,7 @@ bool ProtocolConformance::isCanonical() const { return true; } case ProtocolConformanceKind::Builtin: { - // Check that the generic signature of the conformance is canonical. - auto builtinConformance = cast(this); - if (builtinConformance->getGenericSignature() - && !builtinConformance->getGenericSignature()->isCanonical()) { - return false; - } - // Check that the satisfied conditional requirements are canonical. - for (auto &requirement : builtinConformance->getConditionalRequirements()) { - if (!requirement.isCanonical()) { - return false; - } - } + // FIXME: Not the conforming type? return true; } case ProtocolConformanceKind::Inherited: { @@ -1458,15 +1440,9 @@ ProtocolConformance *ProtocolConformance::getCanonicalConformance() { // Canonicalize the subject type of the builtin conformance. auto &Ctx = getType()->getASTContext(); auto builtinConformance = cast(this); - SmallVector canonicalRequirements; - for (auto &reqt : builtinConformance->getConditionalRequirements()) { - canonicalRequirements.push_back(reqt.getCanonical()); - } return Ctx.getBuiltinConformance( builtinConformance->getType()->getCanonicalType(), builtinConformance->getProtocol(), - builtinConformance->getGenericSignature().getCanonicalSignature(), - canonicalRequirements, builtinConformance->getBuiltinConformanceKind()); } @@ -1496,18 +1472,10 @@ ProtocolConformance *ProtocolConformance::getCanonicalConformance() { BuiltinProtocolConformance::BuiltinProtocolConformance( Type conformingType, ProtocolDecl *protocol, - GenericSignature genericSig, - ArrayRef conditionalRequirements, BuiltinConformanceKind kind ) : RootProtocolConformance(ProtocolConformanceKind::Builtin, conformingType), - protocol(protocol), genericSig(genericSig), - numConditionalRequirements(conditionalRequirements.size()), - builtinConformanceKind(static_cast(kind)) -{ - std::uninitialized_copy(conditionalRequirements.begin(), - conditionalRequirements.end(), - getTrailingObjects()); -} + protocol(protocol), builtinConformanceKind(static_cast(kind)) +{} // See swift/Basic/Statistic.h for declaration: this enables tracing // ProtocolConformances, is defined here to avoid too much layering violation / diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 5c7bc572309ae..a367302869f01 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -160,6 +160,10 @@ bool TypeBase::isPureMoveOnly() { if (auto *nom = getAnyNominal()) return nom->isMoveOnly(); + if (auto *expansion = getAs()) { + return expansion->getPatternType()->isPureMoveOnly(); + } + // if any components of the tuple are move-only, then the tuple is move-only. if (auto *tupl = getCanonicalType()->getAs()) { for (auto eltTy : tupl->getElementTypes()) diff --git a/lib/AST/USRGeneration.cpp b/lib/AST/USRGeneration.cpp index 76ea57c4c9ee8..3fd7b573a22f7 100644 --- a/lib/AST/USRGeneration.cpp +++ b/lib/AST/USRGeneration.cpp @@ -176,7 +176,8 @@ swift::USRGenerationRequest::evaluate(Evaluator &evaluator, if (!D->hasName() && !isa(D) && !isa(D)) return std::string(); // Ignore. - if (D->getModuleContext()->isBuiltinModule()) + if (D->getModuleContext()->isBuiltinModule() && + !isa(D)) return std::string(); // Ignore. if (isa(D)) return std::string(); // Ignore. diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index a0cd3082048fe..88b0245898aff 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -4590,11 +4590,6 @@ namespace { Impl.SwiftContext.evaluator.cacheOutput(ExtendedNominalRequest{result}, std::move(objcClass)); - // Determine the type and generic args of the extension. - if (objcClass->getGenericParams()) { - result->setGenericSignature(objcClass->getGenericSignature()); - } - // Create the extension declaration and record it. objcClass->addExtension(result); Impl.ImportedDecls[{decl, getVersion()}] = result; @@ -9241,7 +9236,7 @@ void ClangImporter::Implementation::loadAllConformances( for (auto *protocol : getImportedProtocols(decl)) { // FIXME: Build a superclass conformance if the superclass // conforms. - auto conformance = SwiftContext.getConformance( + auto conformance = SwiftContext.getNormalConformance( dc->getDeclaredInterfaceType(), protocol, SourceLoc(), dc, ProtocolConformanceState::Incomplete, diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp index 3d90f06fe8093..ee6c41d064562 100644 --- a/lib/Demangling/Demangler.cpp +++ b/lib/Demangling/Demangler.cpp @@ -61,6 +61,7 @@ static bool isAnyGeneric(Node::Kind kind) { case Node::Kind::OtherNominalType: case Node::Kind::TypeAlias: case Node::Kind::TypeSymbolicReference: + case Node::Kind::BuiltinTupleType: return true; default: return false; @@ -110,6 +111,8 @@ bool swift::Demangle::isContext(Node::Kind kind) { case Node::Kind::ID: #include "swift/Demangling/DemangleNodes.def" return true; + case Node::Kind::BuiltinTupleType: + return true; default: return false; } @@ -1426,6 +1429,13 @@ NodePointer Demangler::demangleBuiltinType() { Ty = createNode(Node::Kind::BuiltinTypeName, BUILTIN_TYPE_NAME_WORD); break; + case 'P': + Ty = createNode(Node::Kind::BuiltinTypeName, + BUILTIN_TYPE_NAME_PACKINDEX); + break; + case 'T': + Ty = createNode(Node::Kind::BuiltinTupleType); + break; default: return nullptr; } diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp index 474921a590216..47221fff395cc 100644 --- a/lib/Demangling/NodePrinter.cpp +++ b/lib/Demangling/NodePrinter.cpp @@ -295,6 +295,7 @@ class NodePrinter { case Node::Kind::BoundGenericTypeAlias: case Node::Kind::BoundGenericFunction: case Node::Kind::BuiltinTypeName: + case Node::Kind::BuiltinTupleType: case Node::Kind::Class: case Node::Kind::DependentGenericType: case Node::Kind::DependentMemberType: @@ -1848,6 +1849,9 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth, case Node::Kind::BuiltinTypeName: Printer << Node->getText(); return nullptr; + case Node::Kind::BuiltinTupleType: + Printer << "Builtin.TheTupleType"; + return nullptr; case Node::Kind::Number: Printer << Node->getIndex(); return nullptr; diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp index e9fa885670e5e..c7512f684fd18 100644 --- a/lib/Demangling/OldRemangler.cpp +++ b/lib/Demangling/OldRemangler.cpp @@ -1555,6 +1555,10 @@ ManglingError Remangler::mangleBuiltinTypeName(Node *node, unsigned depth) { return ManglingError::Success; } +ManglingError Remangler::mangleBuiltinTupleType(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnexpectedBuiltinType, node); +} + ManglingError Remangler::mangleTypeAlias(Node *node, EntityContext &ctx, unsigned depth) { return mangleAnyNominalType(node, ctx, depth + 1); diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp index 6c02f04600868..9ed26885a57ea 100644 --- a/lib/Demangling/Remangler.cpp +++ b/lib/Demangling/Remangler.cpp @@ -867,6 +867,8 @@ ManglingError Remangler::mangleBuiltinTypeName(Node *node, unsigned depth) { Buffer << 'I'; } else if (text == BUILTIN_TYPE_NAME_WORD) { Buffer << 'w'; + } else if (text == BUILTIN_TYPE_NAME_PACKINDEX) { + Buffer << 'P'; } else if (text.consume_front(BUILTIN_TYPE_NAME_INT)) { Buffer << 'i' << text << '_'; } else if (text.consume_front(BUILTIN_TYPE_NAME_FLOAT)) { @@ -892,6 +894,11 @@ ManglingError Remangler::mangleBuiltinTypeName(Node *node, unsigned depth) { return ManglingError::Success; } +ManglingError Remangler::mangleBuiltinTupleType(Node *node, unsigned depth) { + Buffer << "BT"; + return ManglingError::Success; +} + ManglingError Remangler::mangleCFunctionPointer(Node *node, unsigned depth) { if (node->getNumChildren() > 0 && node->getFirstChild()->getKind() == Node::Kind::ClangType) { diff --git a/lib/SIL/IR/SIL.cpp b/lib/SIL/IR/SIL.cpp index 805b6ef32b8cd..033a3e8941524 100644 --- a/lib/SIL/IR/SIL.cpp +++ b/lib/SIL/IR/SIL.cpp @@ -82,7 +82,7 @@ swift::getLinkageForProtocolConformance(const RootProtocolConformance *C, if (isa(C->getDeclContext()->getModuleScopeContext())) return SILLinkage::Shared; - auto typeDecl = C->getType()->getNominalOrBoundGenericNominal(); + auto typeDecl = C->getDeclContext()->getSelfNominalTypeDecl(); AccessLevel access = std::min(C->getProtocol()->getEffectiveAccess(), typeDecl->getEffectiveAccess()); switch (access) { diff --git a/lib/SIL/IR/SILWitnessTable.cpp b/lib/SIL/IR/SILWitnessTable.cpp index 8c6852f1c499b..f8a06c5e74045 100644 --- a/lib/SIL/IR/SILWitnessTable.cpp +++ b/lib/SIL/IR/SILWitnessTable.cpp @@ -174,7 +174,7 @@ bool SILWitnessTable::conformanceIsSerialized( if (conformance->getProtocol()->getEffectiveAccess() < AccessLevel::Public) return false; - auto *nominal = conformance->getType()->getAnyNominal(); + auto *nominal = conformance->getDeclContext()->getSelfNominalTypeDecl(); return nominal->getEffectiveAccess() >= AccessLevel::Public; } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 5e06aa3a7756c..e5a75903c468b 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -8293,6 +8293,17 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint( return SolutionKind::Solved; } + // We sometimes get a pack expansion type here. + if (auto *expansionType = type->getAs()) { + // FIXME: Locator + addConstraint(ConstraintKind::ConformsTo, + expansionType->getPatternType(), + protocol->getDeclaredInterfaceType(), + locator); + + return SolutionKind::Solved; + } + // Copyable is checked structurally, so for better performance, split apart // this constraint into individual Copyable constraints on each tuple element. if (auto *tupleType = type->getAs()) { diff --git a/lib/Sema/CodeSynthesisDistributedActor.cpp b/lib/Sema/CodeSynthesisDistributedActor.cpp index 654e86434959b..31748c5926f21 100644 --- a/lib/Sema/CodeSynthesisDistributedActor.cpp +++ b/lib/Sema/CodeSynthesisDistributedActor.cpp @@ -805,10 +805,11 @@ addDistributedActorCodableConformance( return nullptr; } - auto conformance = C.getConformance(actor->getDeclaredInterfaceType(), proto, - actor->getLoc(), /*dc=*/actor, - ProtocolConformanceState::Incomplete, - /*isUnchecked=*/false); + auto conformance = C.getNormalConformance( + actor->getDeclaredInterfaceType(), proto, + actor->getLoc(), /*dc=*/actor, + ProtocolConformanceState::Incomplete, + /*isUnchecked=*/false); conformance->setSourceKindAndImplyingConformance( ConformanceEntryKind::Synthesized, nullptr); actor->registerProtocolConformance(conformance, /*synthesized=*/true); diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp index 4559c880e711d..11517a4c87ec9 100644 --- a/lib/Sema/DerivedConformanceEquatableHashable.cpp +++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp @@ -384,7 +384,7 @@ deriveEquatable_eq( ASTContext &C = derived.Context; auto parentDC = derived.getConformanceContext(); - auto selfIfaceTy = parentDC->getDeclaredInterfaceType(); + auto selfIfaceTy = parentDC->getSelfInterfaceType(); auto getParamDecl = [&](StringRef s) -> ParamDecl * { auto *param = new (C) ParamDecl(SourceLoc(), @@ -970,8 +970,6 @@ getHashableConformance(const Decl *parentDecl) { } bool DerivedConformance::canDeriveHashable(NominalTypeDecl *type) { - if (!isa(type) && !isa(type) && !isa(type)) - return false; // FIXME: This is not actually correct. We cannot promise to always // provide a witness here in all cases. Unfortunately, figuring out // whether this is actually possible requires a parent decl context. diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index 724050fb7d950..de5bb4f138fb0 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -23,6 +23,7 @@ #include "swift/AST/GenericEnvironment.h" #include "swift/AST/Initializer.h" #include "swift/AST/NameLookup.h" +#include "swift/AST/PackConformance.h" #include "swift/AST/Pattern.h" #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/ProtocolConformance.h" @@ -4011,7 +4012,18 @@ swift::diagnoseConformanceAvailability(SourceLoc loc, bool useConformanceAvailabilityErrorsOption) { assert(!where.isImplicit()); - if (!conformance.isConcrete()) + if (conformance.isPack()) { + bool diagnosed = false; + auto *pack = conformance.getPack(); + for (auto patternConf : pack->getPatternConformances()) { + diagnosed |= diagnoseConformanceAvailability( + loc, patternConf, where, depTy, replacementTy, + useConformanceAvailabilityErrorsOption); + } + return diagnosed; + } + + if (conformance.isInvalid() || conformance.isAbstract()) return false; const ProtocolConformance *concreteConf = conformance.getConcrete(); diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index 431d2dfe154ab..47de9d55b222e 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -4914,7 +4914,7 @@ ProtocolConformance *GetImplicitSendableRequest::evaluate( conformanceDC = extension; } - auto conformance = ctx.getConformance( + auto conformance = ctx.getNormalConformance( nominal->getDeclaredInterfaceType(), proto, nominal->getLoc(), conformanceDC, ProtocolConformanceState::Complete, /*isUnchecked=*/attrMakingUnavailable != nullptr); diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index ff937c549afd6..17cabfd6f2c39 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -2371,7 +2371,6 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const { case DeclKind::Module: case DeclKind::OpaqueType: case DeclKind::GenericTypeParam: - case DeclKind::BuiltinTuple: case DeclKind::MacroExpansion: llvm_unreachable("should not get here"); return Type(); @@ -2402,7 +2401,8 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const { case DeclKind::Enum: case DeclKind::Struct: case DeclKind::Class: - case DeclKind::Protocol: { + case DeclKind::Protocol: + case DeclKind::BuiltinTuple: { auto nominal = cast(D); Type declaredInterfaceTy = nominal->getDeclaredInterfaceType(); // FIXME: For a protocol, this returns a MetatypeType wrapping a ProtocolType, but should be a MetatypeType wrapping an ExistentialType ('(any P).Type', not 'P.Type'). diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 027a702eac185..f4b7cd5951936 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -3505,6 +3505,13 @@ class DeclChecker : public DeclVisitor { auto extType = ED->getExtendedType(); auto *nominal = ED->getExtendedNominal(); + + // Diagnose experimental tuple extensions. + if (nominal && isa(nominal) && + !getASTContext().LangOpts.hasFeature(Feature::TupleConformances)) { + ED->diagnose(diag::experimental_tuple_extension); + } + if (nominal == nullptr) { const bool wasAlreadyInvalid = ED->isInvalid(); ED->setInvalid(); diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 84eee24c09504..42df816283595 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -5700,8 +5700,7 @@ TypeChecker::containsProtocol(Type T, ProtocolDecl *Proto, ModuleDecl *M, Proto->isSpecificProtocol(KnownProtocolKind::Sendable)) { return ProtocolConformanceRef( M->getASTContext().getBuiltinConformance( - T, Proto, GenericSignature(), { }, - BuiltinConformanceKind::Missing)); + T, Proto, BuiltinConformanceKind::Missing)); } return ProtocolConformanceRef::forInvalid(); diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index a9c33ed5d319b..2614d1f8d4ad1 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -844,13 +844,9 @@ ProtocolConformanceDeserializer::readBuiltinProtocolConformance( TypeID conformingTypeID; DeclID protoID; - GenericSignatureID genericSigID; unsigned builtinConformanceKind; - ArrayRef data; BuiltinProtocolConformanceLayout::readRecord(scratch, conformingTypeID, - protoID, genericSigID, - builtinConformanceKind, - data); + protoID, builtinConformanceKind); Type conformingType = MF.getType(conformingTypeID); @@ -859,22 +855,9 @@ ProtocolConformanceDeserializer::readBuiltinProtocolConformance( return decl.takeError(); auto proto = cast(decl.get()); - auto genericSig = MF.getGenericSignatureChecked(genericSigID); - if (!genericSig) - return genericSig.takeError(); - - // Read the conditional requirements. - SmallVector conditionalRequirements; - unsigned nextDataIndex = 0; - auto error = MF.deserializeGenericRequirementsChecked( - data, nextDataIndex, conditionalRequirements); - if (error) - return std::move(error); - if (nextDataIndex != data.size()) - return MF.diagnoseFatal(); auto conformance = ctx.getBuiltinConformance( - conformingType, proto, *genericSig, conditionalRequirements, + conformingType, proto, static_cast(builtinConformanceKind)); return conformance; } @@ -951,9 +934,10 @@ ProtocolConformanceDeserializer::readNormalProtocolConformance( PrettyStackTraceDecl traceTo("... to", proto); - auto conformance = ctx.getConformance(conformingType, proto, SourceLoc(), dc, - ProtocolConformanceState::Incomplete, - isUnchecked); + auto conformance = ctx.getNormalConformance( + conformingType, proto, SourceLoc(), dc, + ProtocolConformanceState::Incomplete, + isUnchecked); // Record this conformance. if (conformanceEntry.isComplete()) { assert(conformanceEntry.get() == conformance); diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 5de33709a5961..3f8867b298bc0 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,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 = 800; // added unowned_copy_value +const uint16_t SWIFTMODULE_VERSION_MINOR = 801; // removing builtin tuple conformances /// A standard hash seed used for all string hashes in a serialized module. /// @@ -1951,9 +1951,7 @@ namespace decls_block { BUILTIN_PROTOCOL_CONFORMANCE, TypeIDField, // the conforming type DeclIDField, // the protocol - GenericSignatureIDField, // the generic signature - BCFixed<2>, // the builtin conformance kind - BCArray> // conditional requirements + BCFixed<2> // the builtin conformance kind >; using PackConformanceLayout = BCRecordLayout< diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 9cf5156e19b8b..a8066de37fa6d 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -1842,16 +1842,10 @@ Serializer::writeASTBlockEntity(ProtocolConformance *conformance) { DeclTypeAbbrCodes[BuiltinProtocolConformanceLayout::Code]; auto typeID = addTypeRef(builtin->getType()); auto protocolID = addDeclRef(builtin->getProtocol()); - auto genericSigID = addGenericSignatureRef(builtin->getGenericSignature()); - - SmallVector requirementData; - serializeGenericRequirements(builtin->getConditionalRequirements(), - requirementData); BuiltinProtocolConformanceLayout::emitRecord( - Out, ScratchRecord, abbrCode, typeID, protocolID, genericSigID, - static_cast(builtin->getBuiltinConformanceKind()), - requirementData); + Out, ScratchRecord, abbrCode, typeID, protocolID, + static_cast(builtin->getBuiltinConformanceKind())); break; } } diff --git a/test/Generics/tuple-conformances.swift b/test/Generics/tuple-conformances.swift index 5aa7fe4a85acd..4977a57013483 100644 --- a/test/Generics/tuple-conformances.swift +++ b/test/Generics/tuple-conformances.swift @@ -38,6 +38,8 @@ func useConformance() { //// extension Builtin.TheTupleType: Equatable where repeat each Elements: Equatable { + // FIXME: Hack + @_disfavoredOverload public static func ==(lhs: Self, rhs: Self) -> Bool { var result = true func update(lhs: E, rhs: E) { @@ -53,9 +55,4 @@ extension Builtin.TheTupleType: Hashable where repeat each Elements: Hashable { public func hash(into hasher: inout Hasher) { repeat (each self).hash(into: &hasher) } - - // FIXME: This should be unnecessary - public var hashValue: Int { - return 0 - } } diff --git a/test/Sema/pack_conformance_availability.swift b/test/Sema/pack_conformance_availability.swift new file mode 100644 index 0000000000000..12867f986e5cc --- /dev/null +++ b/test/Sema/pack_conformance_availability.swift @@ -0,0 +1,14 @@ +// RUN: %target-typecheck-verify-swift + +func f(_: repeat each T) {} + +protocol P {} + +struct S {} + +@available(*, unavailable) +extension S: P {} +// expected-note@-1 {{conformance of 'S' to 'P' has been explicitly marked unavailable here}} + +f(S()) +// expected-error@-1 {{conformance of 'S' to 'P' is unavailable}}