void layout() override { PrettyStackTraceDecl DebugStack("emitting field type metadata", NTD); auto type = NTD->getDeclaredType()->getCanonicalType(); addTypeRef(NTD->getModuleContext(), type); if (NTD->hasClangNode() && !isa<ClassDecl>(NTD) && !isa<ProtocolDecl>(NTD)) return; switch (NTD->getKind()) { case DeclKind::Class: case DeclKind::Struct: layoutRecord(); break; case DeclKind::Enum: layoutEnum(); break; case DeclKind::Protocol: layoutProtocol(); break; default: llvm_unreachable("Not a nominal type"); break; } }
bool IRGenerator::canEmitWitnessTableLazily(SILWitnessTable *wt) { if (Opts.UseJIT) return false; // Regardless of the access level, if the witness table is shared it means // we can safely not emit it. Every other module which needs it will generate // its own shared copy of it. if (wt->getLinkage() == SILLinkage::Shared) return true; NominalTypeDecl *ConformingTy = wt->getConformingType()->getNominalOrBoundGenericNominal(); switch (ConformingTy->getEffectiveAccess()) { case AccessLevel::Private: case AccessLevel::FilePrivate: return true; case AccessLevel::Internal: return PrimaryIGM->getSILModule().isWholeModule(); default: return false; } llvm_unreachable("switch does not handle all cases"); }
SmallVector<ProtocolDecl *, 2> DeclContext::getLocalProtocols( ConformanceLookupKind lookupKind, SmallVectorImpl<ConformanceDiagnostic> *diagnostics, bool sorted) const { SmallVector<ProtocolDecl *, 2> result; // Dig out the nominal type. NominalTypeDecl *nominal = getAsNominalTypeOrNominalTypeExtensionContext(); if (!nominal) return result; // Update to record all potential conformances. nominal->prepareConformanceTable(); nominal->ConformanceTable->lookupConformances( nominal, const_cast<DeclContext *>(this), getASTContext().getLazyResolver(), lookupKind, &result, nullptr, diagnostics); // Sort if required. if (sorted) { llvm::array_pod_sort(result.begin(), result.end(), &ProtocolType::compareProtocols); } return result; }
static Type findBaseTypeForReplacingArchetype(const ValueDecl *VD, const Type Ty) { if (Ty.isNull()) return Type(); // Find the nominal type decl related to VD. auto TC = VD->getDeclContext()->getInnermostTypeContext(); NominalTypeDecl *NTD = dyn_cast_or_null<NominalTypeDecl>(TC); if (!NTD) { ExtensionDecl *ED = dyn_cast_or_null<ExtensionDecl>(TC); if (ED) { if (auto T = ED->getExtendedType()) NTD = T->getAnyNominal(); } } if (!NTD) return Type(); Type Result; // Walk the type tree to find the a sub-type who's convertible to the // found nominal. Ty.visit([&](Type T) { if (!Result && (T->getAnyNominal() == NTD || isConvertibleTo(T, NTD->getDeclaredType(), VD->getDeclContext()))) { Result = T; } }); return Result; }
void layoutRecord() { auto kind = FieldDescriptorKind::Struct; if (auto CD = dyn_cast<ClassDecl>(NTD)) { auto type = CD->getDeclaredType()->getCanonicalType(); auto RC = getReferenceCountingForType(IGM, type); if (RC == ReferenceCounting::ObjC) kind = FieldDescriptorKind::ObjCClass; else kind = FieldDescriptorKind::Class; } B.addInt16(uint16_t(kind)); B.addInt16(fieldRecordSize); // Imported classes don't need field descriptors if (NTD->hasClangNode() && isa<ClassDecl>(NTD)) { B.addInt32(0); return; } assert(!NTD->hasClangNode() || isa<StructDecl>(NTD)); auto properties = NTD->getStoredProperties(); B.addInt32(std::distance(properties.begin(), properties.end())); for (auto property : properties) addFieldDecl(property, property->getInterfaceType() ->getCanonicalType()); }
static void lookupDeclsFromProtocolsBeingConformedTo( Type BaseTy, VisibleDeclConsumer &Consumer, LookupState LS, const DeclContext *FromContext, DeclVisibilityKind Reason, LazyResolver *TypeResolver, VisitedSet &Visited) { NominalTypeDecl *CurrNominal = BaseTy->getAnyNominal(); if (!CurrNominal) return; for (auto Conformance : CurrNominal->getAllConformances()) { auto Proto = Conformance->getProtocol(); if (!Proto->isAccessibleFrom(FromContext)) continue; DeclVisibilityKind ReasonForThisProtocol; if (Reason == DeclVisibilityKind::MemberOfCurrentNominal) ReasonForThisProtocol = DeclVisibilityKind::MemberOfProtocolImplementedByCurrentNominal; else ReasonForThisProtocol = getReasonForSuper(Reason); auto NormalConformance = Conformance->getRootNormalConformance(); for (auto Member : Proto->getMembers()) { if (auto *ATD = dyn_cast<AssociatedTypeDecl>(Member)) { // Skip type decls if they aren't visible, or any type that has a // witness. This cuts down on duplicates. if (areTypeDeclsVisibleInLookupMode(LS) && !NormalConformance->hasTypeWitness(ATD)) { Consumer.foundDecl(ATD, ReasonForThisProtocol); } continue; } if (auto *VD = dyn_cast<ValueDecl>(Member)) { if (TypeResolver) { TypeResolver->resolveDeclSignature(VD); if (!NormalConformance->hasWitness(VD) && (Conformance->getDeclContext()->getParentSourceFile() != FromContext->getParentSourceFile())) TypeResolver->resolveWitness(NormalConformance, VD); } // Skip value requirements that have corresponding witnesses. This cuts // down on duplicates. if (!NormalConformance->hasWitness(VD) || !NormalConformance->getWitness(VD, nullptr) || NormalConformance->getWitness(VD, nullptr).getDecl()->getFullName() != VD->getFullName()) { Consumer.foundDecl(VD, ReasonForThisProtocol); } } } // Add members from any extensions. SmallVector<ValueDecl *, 2> FoundDecls; doGlobalExtensionLookup(BaseTy, Proto->getDeclaredType(), FoundDecls, FromContext, LS, ReasonForThisProtocol, TypeResolver); for (auto *VD : FoundDecls) Consumer.foundDecl(VD, ReasonForThisProtocol); } }
void layout() { using swift::reflection::FieldDescriptorKind; PrettyStackTraceDecl DebugStack("emitting field type metadata", NTD); auto type = NTD->getDeclaredType()->getCanonicalType(); addTypeRef(NTD->getModuleContext(), type); switch (NTD->getKind()) { case DeclKind::Class: case DeclKind::Struct: { auto properties = NTD->getStoredProperties(); addConstantInt16(uint16_t(isa<StructDecl>(NTD) ? FieldDescriptorKind::Struct : FieldDescriptorKind::Class)); addConstantInt16(fieldRecordSize); addConstantInt32(std::distance(properties.begin(), properties.end())); for (auto property : properties) addFieldDecl(property, property->getInterfaceType() ->getCanonicalType()); break; } case DeclKind::Enum: { auto enumDecl = cast<EnumDecl>(NTD); auto cases = enumDecl->getAllElements(); addConstantInt16(uint16_t(FieldDescriptorKind::Enum)); addConstantInt16(fieldRecordSize); addConstantInt32(std::distance(cases.begin(), cases.end())); for (auto enumCase : cases) { if (enumCase->hasArgumentType()) { addFieldDecl(enumCase, enumCase->getArgumentInterfaceType() ->getCanonicalType()); } else { addFieldDecl(enumCase, CanType()); } } break; } case DeclKind::Protocol: { auto protocolDecl = cast<ProtocolDecl>(NTD); FieldDescriptorKind Kind; if (protocolDecl->isObjC()) Kind = FieldDescriptorKind::ObjCProtocol; else if (protocolDecl->requiresClass()) Kind = FieldDescriptorKind::ClassProtocol; else Kind = FieldDescriptorKind::Protocol; addConstantInt16(uint16_t(Kind)); addConstantInt16(fieldRecordSize); addConstantInt32(0); break; } default: llvm_unreachable("Not a nominal type"); break; } }
/// Recursively traverse the conformance lists to determine sole conforming /// class, struct or enum type. NominalTypeDecl * ProtocolConformanceAnalysis::findSoleConformingType(ProtocolDecl *Protocol) { /// First check in the SoleConformingTypeCache. auto SoleConformingTypeIt = SoleConformingTypeCache.find(Protocol); if (SoleConformingTypeIt != SoleConformingTypeCache.end()) return SoleConformingTypeIt->second; SmallVector<ProtocolDecl *, 8> PDWorkList; SmallPtrSet<ProtocolDecl *, 8> VisitedPDs; NominalTypeDecl *SoleConformingNTD = nullptr; PDWorkList.push_back(Protocol); while (!PDWorkList.empty()) { auto *PD = PDWorkList.pop_back_val(); // Protocols must have internal or lower access. if (PD->getEffectiveAccess() > AccessLevel::Internal) { return nullptr; } VisitedPDs.insert(PD); auto NTDList = getConformances(PD); for (auto *ConformingNTD : NTDList) { // Recurse on protocol types. if (auto *Proto = dyn_cast<ProtocolDecl>(ConformingNTD)) { // Ignore visited protocol decls. if (!VisitedPDs.count(Proto)) PDWorkList.push_back(Proto); } else { // Classes, Structs and Enums are added here. // Bail if more than one conforming types were found. if (SoleConformingNTD && ConformingNTD != SoleConformingNTD) { return nullptr; } else { SoleConformingNTD = ConformingNTD; } } } } // Bail if we did not find a sole conforming type. if (!SoleConformingNTD) return nullptr; // Generic declarations are ignored. if (SoleConformingNTD->isGenericContext()) { return nullptr; } // Populate SoleConformingTypeCache. SoleConformingTypeCache.insert(std::pair<ProtocolDecl *, NominalTypeDecl *>( Protocol, SoleConformingNTD)); // Return SoleConformingNTD. return SoleConformingNTD; }
static unsigned getIndexForValueDecl(ValueDecl *Decl) { NominalTypeDecl *D = cast<NominalTypeDecl>(Decl->getDeclContext()); unsigned i = 0; for (auto *V : D->getStoredProperties()) { if (V == Decl) return i; ++i; } llvm_unreachable("Failed to find Decl in its decl context?!"); }
static bool shouldPrintAsFavorable(const Decl *D, PrintOptions &Options) { if (!Options.TransformContext || !D->getDeclContext()->isExtensionContext() || !Options.TransformContext->isPrintingSynthesizedExtension()) return true; NominalTypeDecl *Target = Options.TransformContext->getNominal(); Type BaseTy = Target->getDeclaredTypeInContext(); const auto *FD = dyn_cast<FuncDecl>(D); if (!FD) return true; ResolvedMemberResult Result = resolveValueMember(*Target->getDeclContext(), BaseTy, FD->getEffectiveFullName()); return !(Result.hasBestOverload() && Result.getBestOverload() != D); }
Implementation(NominalTypeDecl *Target, bool IncludeUnconditional, PrintOptions Options): Target(Target), BaseType(Target->getDeclaredInterfaceType()), DC(Target), IncludeUnconditional(IncludeUnconditional), Options(Options), AllGroups(MergeGroupVector()), InfoMap(collectSynthesizedExtensionInfo(AllGroups)) {}
bool IRGenerator::canEmitWitnessTableLazily(SILWitnessTable *wt) { if (Opts.UseJIT) return false; NominalTypeDecl *ConformingTy = wt->getConformance()->getType()->getNominalOrBoundGenericNominal(); switch (ConformingTy->getEffectiveAccess()) { case AccessLevel::Private: case AccessLevel::FilePrivate: return true; case AccessLevel::Internal: return PrimaryIGM->getSILModule().isWholeModule(); default: return false; } llvm_unreachable("switch does not handle all cases"); }
/// \brief Enumerate immediate members of the type \c LookupType and its /// extensions, as seen from the context \c CurrDC. /// /// Don't do lookup into superclasses or implemented protocols. Uses /// \p BaseType as the underlying type when checking any constraints on the /// extensions. static void lookupTypeMembers(Type BaseType, Type LookupType, VisibleDeclConsumer &Consumer, const DeclContext *CurrDC, LookupState LS, DeclVisibilityKind Reason, LazyResolver *TypeResolver) { NominalTypeDecl *D = LookupType->getAnyNominal(); assert(D && "should have a nominal type"); bool LookupFromChildDeclContext = false; const DeclContext *TempDC = CurrDC; while (!TempDC->isModuleContext()) { if (TempDC == D) { LookupFromChildDeclContext = true; break; } TempDC = TempDC->getParent(); } SmallVector<ValueDecl*, 2> FoundDecls; if (LookupFromChildDeclContext) { // Current decl context is contained inside 'D', so generic parameters // are visible. if (D->getGenericParams()) for (auto Param : *D->getGenericParams()) if (isDeclVisibleInLookupMode(Param, LS, CurrDC, TypeResolver)) FoundDecls.push_back(Param); } for (Decl *Member : D->getMembers()) { if (auto *VD = dyn_cast<ValueDecl>(Member)) if (isDeclVisibleInLookupMode(VD, LS, CurrDC, TypeResolver)) FoundDecls.push_back(VD); } doGlobalExtensionLookup(BaseType, LookupType, FoundDecls, CurrDC, LS, Reason, TypeResolver); // Report the declarations we found to the consumer. for (auto *VD : FoundDecls) Consumer.foundDecl(VD, Reason); }
void findExtensionsFromConformingProtocols(Decl *D, llvm::SmallPtrSetImpl<ExtensionDecl*> &Results) { NominalTypeDecl* NTD = dyn_cast<NominalTypeDecl>(D); if (!NTD || NTD->getKind() == DeclKind::Protocol) return; std::vector<NominalTypeDecl*> Unhandled; auto addTypeLocNominal = [&](TypeLoc TL){ if (TL.getType()) { if (auto D = TL.getType()->getAnyNominal()) { Unhandled.push_back(D); } } }; for (auto TL : NTD->getInherited()) { addTypeLocNominal(TL); } while(!Unhandled.empty()) { NominalTypeDecl* Back = Unhandled.back(); Unhandled.pop_back(); for (ExtensionDecl *E : Back->getExtensions()) { if(E->isConstrainedExtension()) Results.insert(E); for (auto TL : Back->getInherited()) { addTypeLocNominal(TL); } } } }
static Type findBaseTypeForReplacingArchetype(const ValueDecl *VD, const Type Ty) { if (Ty.isNull()) return Type(); // Find the nominal type decl related to VD. NominalTypeDecl *NTD = VD->getDeclContext()-> getAsNominalTypeOrNominalTypeExtensionContext(); if (!NTD) return Type(); Type Result; // Walk the type tree to find the a sub-type who's convertible to the // found nominal. Ty.visit([&](Type T) { if (!Result && (T->getAnyNominal() == NTD || isConvertibleTo(T, NTD->getDeclaredType(), VD->getDeclContext()))) { Result = T; } }); return Result; }
/// Enumerate immediate members of the type \c LookupType and its /// extensions, as seen from the context \c CurrDC. /// /// Don't do lookup into superclasses or implemented protocols. Uses /// \p BaseType as the underlying type when checking any constraints on the /// extensions. static void lookupTypeMembers(Type BaseType, Type LookupType, VisibleDeclConsumer &Consumer, const DeclContext *CurrDC, LookupState LS, DeclVisibilityKind Reason, LazyResolver *TypeResolver) { NominalTypeDecl *D = LookupType->getAnyNominal(); assert(D && "should have a nominal type"); SmallVector<ValueDecl*, 2> FoundDecls; for (Decl *Member : D->getMembers()) { if (auto *VD = dyn_cast<ValueDecl>(Member)) if (isDeclVisibleInLookupMode(VD, LS, CurrDC, TypeResolver)) FoundDecls.push_back(VD); } doGlobalExtensionLookup(BaseType, LookupType, FoundDecls, CurrDC, LS, Reason, TypeResolver); // Report the declarations we found to the consumer. for (auto *VD : FoundDecls) Consumer.foundDecl(VD, Reason); }
SmallVector<ProtocolConformance *, 2> DeclContext::getLocalConformances( ConformanceLookupKind lookupKind, SmallVectorImpl<ConformanceDiagnostic> *diagnostics, bool sorted) const { SmallVector<ProtocolConformance *, 2> result; // Dig out the nominal type. NominalTypeDecl *nominal = isNominalTypeOrNominalTypeExtensionContext(); if (!nominal) return result; // Protocols don't have conformances. if (isa<ProtocolDecl>(nominal)) return { }; // Update to record all potential conformances. nominal->prepareConformanceTable(); nominal->ConformanceTable->lookupConformances( nominal, const_cast<DeclContext *>(this), nominal->getASTContext().getLazyResolver(), lookupKind, nullptr, &result, diagnostics); // If requested, sort the results. if (sorted) { llvm::array_pod_sort(result.begin(), result.end(), &ConformanceLookupTable::compareProtocolConformances); } return result; }
void layout() override { if (NTD->hasClangNode() && !isa<ClassDecl>(NTD) && !isa<StructDecl>(NTD) && !isa<ProtocolDecl>(NTD)) return; PrettyStackTraceDecl DebugStack("emitting field type metadata", NTD); addNominalRef(NTD); auto *CD = dyn_cast<ClassDecl>(NTD); if (CD && CD->getSuperclass()) { addTypeRef(CD->getSuperclass()->getCanonicalType()); } else { B.addInt32(0); } switch (NTD->getKind()) { case DeclKind::Class: case DeclKind::Struct: layoutRecord(); break; case DeclKind::Enum: layoutEnum(); break; case DeclKind::Protocol: layoutProtocol(); break; default: llvm_unreachable("Not a nominal type"); break; } }
std::unique_ptr<ExtensionInfoMap> collectSynthesizedExtensionInfoForProtocol(MergeGroupVector &AllGroups) { std::unique_ptr<ExtensionInfoMap> InfoMap(new ExtensionInfoMap()); ExtensionMergeInfoMap MergeInfoMap; for (auto *E : Target->getExtensions()) { if (!Options.shouldPrint(E)) continue; auto Pair = isApplicable(E, /*Synthesized*/false); if (Pair.first) { InfoMap->insert({E, Pair.first}); MergeInfoMap.insert({E, Pair.second}); } } populateMergeGroup(*InfoMap, MergeInfoMap, AllGroups, /*AllowMergeWithDefBody*/false); std::sort(AllGroups.begin(), AllGroups.end()); for (auto &Group : AllGroups) { Group.sortMembers(); } return InfoMap; }
//===----------------------------------------------------------------------===// // Qualified name lookup handling //===----------------------------------------------------------------------===// bool IterativeTypeChecker::isQualifiedLookupInDeclContextSatisfied( TypeCheckRequest::DeclContextLookupPayloadType payload) { auto dc = payload.DC; NominalTypeDecl *nominal = nullptr; switch (dc->getContextKind()) { case DeclContextKind::AbstractClosureExpr: case DeclContextKind::AbstractFunctionDecl: case DeclContextKind::Initializer: case DeclContextKind::TopLevelCodeDecl: case DeclContextKind::SerializedLocal: case DeclContextKind::SubscriptDecl: llvm_unreachable("not a DeclContext that supports name lookup"); case DeclContextKind::Module: case DeclContextKind::FileUnit: // Modules and file units can always handle name lookup. return true; case DeclContextKind::GenericTypeDecl: // Get the nominal type. nominal = dyn_cast<NominalTypeDecl>(cast<GenericTypeDecl>(dc)); if (!nominal) return true; break; case DeclContextKind::ExtensionDecl: { auto ext = cast<ExtensionDecl>(dc); // FIXME: bind the extension. We currently assume this is done. nominal = ext->getAsNominalTypeOrNominalTypeExtensionContext(); if (!nominal) return true; break; } } assert(nominal && "Only nominal types are handled here"); // FIXME: Cache a bit indicating when qualified lookup is possible. // If we needed them for this query, did we already add implicit // initializers? auto name = payload.Name; if ((!name || name.matchesRef(getASTContext().Id_init)) && !nominal->addedImplicitInitializers()) return false; // For classes, check the superclass. if (auto classDecl = dyn_cast<ClassDecl>(nominal)) { if (!isSatisfied(requestTypeCheckSuperclass(classDecl))) return false; if (auto superclass = classDecl->getSuperclass()) { if (auto superclassDecl = superclass->getAnyNominal()) { if (!isSatisfied(requestQualifiedLookupInDeclContext({ superclassDecl, payload.Name, payload.Loc }))) return false; } } } return true; }
std::unique_ptr<ExtensionInfoMap> collectSynthesizedExtensionInfo(MergeGroupVector &AllGroups) { if (isa<ProtocolDecl>(Target)) { return collectSynthesizedExtensionInfoForProtocol(AllGroups); } std::unique_ptr<ExtensionInfoMap> InfoMap(new ExtensionInfoMap()); ExtensionMergeInfoMap MergeInfoMap; std::vector<NominalTypeDecl*> Unhandled; auto handleExtension = [&](ExtensionDecl *E, bool Synthesized, ExtensionDecl *EnablingE, NormalProtocolConformance *Conf) { if (Options.shouldPrint(E)) { auto Pair = isApplicable(E, Synthesized, EnablingE, Conf); if (Pair.first) { InfoMap->insert({E, Pair.first}); MergeInfoMap.insert({E, Pair.second}); } } }; for (auto *Conf : Target->getLocalConformances()) { Unhandled.push_back(Conf->getProtocol()); } if (auto *CD = dyn_cast<ClassDecl>(Target)) { if (auto Super = CD->getSuperclassDecl()) Unhandled.push_back(Super); } while (!Unhandled.empty()) { NominalTypeDecl* Back = Unhandled.back(); Unhandled.pop_back(); for (ExtensionDecl *E : Back->getExtensions()) { handleExtension(E, true, nullptr, nullptr); } for (auto *Conf : Back->getLocalConformances()) { Unhandled.push_back(Conf->getProtocol()); } if (auto *CD = dyn_cast<ClassDecl>(Back)) { if (auto Super = CD->getSuperclass()) Unhandled.push_back(Super->getAnyNominal()); } } // Merge with actual extensions. for (auto *EnablingE : Target->getExtensions()) { handleExtension(EnablingE, false, nullptr, nullptr); for (auto *Conf : EnablingE->getLocalConformances()) { for (auto E : Conf->getProtocol()->getExtensions()) handleExtension(E, true, EnablingE, Conf->getRootNormalConformance()); } } populateMergeGroup(*InfoMap, MergeInfoMap, AllGroups, /*AllowMergeWithDefBody*/true); std::sort(AllGroups.begin(), AllGroups.end()); for (auto &Group : AllGroups) { Group.removeUnfavored(Target); Group.sortMembers(); } AllGroups.erase(std::remove_if(AllGroups.begin(), AllGroups.end(), [](ExtensionMergeGroup &Group) { return Group.Members.empty(); }), AllGroups.end()); return InfoMap; }
void layout() { using swift::reflection::FieldDescriptorKind; PrettyStackTraceDecl DebugStack("emitting field type metadata", NTD); auto type = NTD->getDeclaredType()->getCanonicalType(); addTypeRef(NTD->getModuleContext(), type); if (NTD->hasClangNode() && !isa<ClassDecl>(NTD) && !isa<ProtocolDecl>(NTD)) return; switch (NTD->getKind()) { case DeclKind::Class: case DeclKind::Struct: { auto kind = FieldDescriptorKind::Struct; if (auto CD = dyn_cast<ClassDecl>(NTD)) { auto RC = getReferenceCountingForClass(IGM, const_cast<ClassDecl *>(CD)); if (RC == ReferenceCounting::ObjC) kind = FieldDescriptorKind::ObjCClass; else kind = FieldDescriptorKind::Class; } addConstantInt16(uint16_t(kind)); addConstantInt16(fieldRecordSize); // Imported classes don't need field descriptors if (NTD->hasClangNode()) { assert(isa<ClassDecl>(NTD)); addConstantInt32(0); break; } auto properties = NTD->getStoredProperties(); addConstantInt32(std::distance(properties.begin(), properties.end())); for (auto property : properties) addFieldDecl(property, property->getInterfaceType() ->getCanonicalType()); break; } case DeclKind::Enum: { auto enumDecl = cast<EnumDecl>(NTD); auto cases = enumDecl->getAllElements(); addConstantInt16(uint16_t(FieldDescriptorKind::Enum)); addConstantInt16(fieldRecordSize); addConstantInt32(std::distance(cases.begin(), cases.end())); for (auto enumCase : cases) { if (enumCase->hasArgumentType()) { addFieldDecl(enumCase, enumCase->getArgumentInterfaceType() ->getCanonicalType()); } else { addFieldDecl(enumCase, CanType()); } } break; } case DeclKind::Protocol: { auto protocolDecl = cast<ProtocolDecl>(NTD); FieldDescriptorKind Kind; if (protocolDecl->isObjC()) Kind = FieldDescriptorKind::ObjCProtocol; else if (protocolDecl->requiresClass()) Kind = FieldDescriptorKind::ClassProtocol; else Kind = FieldDescriptorKind::Protocol; addConstantInt16(uint16_t(Kind)); addConstantInt16(fieldRecordSize); addConstantInt32(0); break; } default: llvm_unreachable("Not a nominal type"); break; } }
static void bindExtensionDecl(ExtensionDecl *ED, TypeChecker &TC) { if (ED->getExtendedType()) return; // If we didn't parse a type, fill in an error type and bail out. if (!ED->getExtendedTypeLoc().getTypeRepr()) { ED->setInvalid(); ED->getExtendedTypeLoc().setInvalidType(TC.Context); return; } auto dc = ED->getDeclContext(); // Validate the representation. // FIXME: Perform some kind of "shallow" validation here? TypeResolutionOptions options; options |= TR_AllowUnboundGenerics; options |= TR_ExtensionBinding; if (TC.validateType(ED->getExtendedTypeLoc(), dc, options)) { ED->setInvalid(); return; } // Dig out the extended type. auto extendedType = ED->getExtendedType(); // Hack to allow extending a generic typealias. if (auto *unboundGeneric = extendedType->getAs<UnboundGenericType>()) { if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(unboundGeneric->getDecl())) { auto extendedNominal = aliasDecl->getDeclaredInterfaceType()->getAnyNominal(); if (extendedNominal) { extendedType = extendedNominal->getDeclaredType(); ED->getExtendedTypeLoc().setType(extendedType); } } } // Handle easy cases. // Cannot extend a metatype. if (extendedType->is<AnyMetatypeType>()) { TC.diagnose(ED->getLoc(), diag::extension_metatype, extendedType) .highlight(ED->getExtendedTypeLoc().getSourceRange()); ED->setInvalid(); ED->getExtendedTypeLoc().setInvalidType(TC.Context); return; } // Cannot extend a bound generic type. if (extendedType->isSpecialized()) { TC.diagnose(ED->getLoc(), diag::extension_specialization, extendedType->getAnyNominal()->getName()) .highlight(ED->getExtendedTypeLoc().getSourceRange()); ED->setInvalid(); ED->getExtendedTypeLoc().setInvalidType(TC.Context); return; } // Dig out the nominal type being extended. NominalTypeDecl *extendedNominal = extendedType->getAnyNominal(); if (!extendedNominal) { TC.diagnose(ED->getLoc(), diag::non_nominal_extension, extendedType) .highlight(ED->getExtendedTypeLoc().getSourceRange()); ED->setInvalid(); ED->getExtendedTypeLoc().setInvalidType(TC.Context); return; } assert(extendedNominal && "Should have the nominal type being extended"); // If the extended type is generic or is a protocol. Clone or create // the generic parameters. if (extendedNominal->isGenericContext()) { if (auto proto = dyn_cast<ProtocolDecl>(extendedNominal)) { // For a protocol extension, build the generic parameter list. ED->setGenericParams(proto->createGenericParams(ED)); } else { // Clone the existing generic parameter list. ED->setGenericParams( cloneGenericParams(TC.Context, ED, extendedNominal->getGenericParamsOfContext())); } } // If we have a trailing where clause, deal with it now. // For now, trailing where clauses are only permitted on protocol extensions. if (auto trailingWhereClause = ED->getTrailingWhereClause()) { if (!extendedNominal->isGenericContext()) { // Only generic and protocol types are permitted to have // trailing where clauses. TC.diagnose(ED, diag::extension_nongeneric_trailing_where, extendedType) .highlight(trailingWhereClause->getSourceRange()); ED->setTrailingWhereClause(nullptr); } else { // Merge the trailing where clause into the generic parameter list. // FIXME: Long-term, we'd like clients to deal with the trailing where // clause explicitly, but for now it's far more direct to represent // the trailing where clause as part of the requirements. ED->getGenericParams()->addTrailingWhereClause( TC.Context, trailingWhereClause->getWhereLoc(), trailingWhereClause->getRequirements()); } } extendedNominal->addExtension(ED); }
ProtocolConformance *ConformanceLookupTable::getConformance( NominalTypeDecl *nominal, LazyResolver *resolver, ConformanceEntry *entry) { // If we already have a conformance, we're done. if (auto conformance = entry->getConformance()) return conformance; ProtocolDecl *protocol = entry->getProtocol(); // Determine where the explicit conformance actually lives. // FIXME: This is a hack to ensure that inherited conformances are // always "single step", which is bad for resilience but is assumed // elsewhere in the compiler. DeclContext *conformingDC = getConformingContext(nominal, resolver, entry); if (!conformingDC) return nullptr; NominalTypeDecl *conformingNominal = conformingDC->isNominalTypeOrNominalTypeExtensionContext(); // Form the conformance. Type type = entry->getDeclContext()->getDeclaredTypeInContext(); ProtocolConformance *conformance; ASTContext &ctx = nominal->getASTContext(); if (entry->getKind() == ConformanceEntryKind::Inherited) { // For an inherited conformance, the conforming nominal type will // be different from the nominal type. assert(conformingNominal != nominal && "Broken inherited conformance"); // Find the superclass type that matches where the conformance was // declared. Type superclassTy = type->getSuperclass(resolver); while (superclassTy->getAnyNominal() != conformingNominal) superclassTy = superclassTy->getSuperclass(resolver); // Look up the inherited conformance. Module *module = entry->getDeclContext()->getParentModule(); auto inheritedConformance = module->lookupConformance(superclassTy, protocol, resolver) .getPointer(); // Form the inherited conformance. conformance = ctx.getInheritedConformance(type, inheritedConformance); } else { // Create or find the normal conformance. Type conformingType = conformingDC->getDeclaredTypeInContext(); SourceLoc conformanceLoc = conformingNominal == conformingDC ? conformingNominal->getLoc() : cast<ExtensionDecl>(conformingDC)->getLoc(); conformance = ctx.getConformance(conformingType, protocol, conformanceLoc, conformingDC, ProtocolConformanceState::Incomplete); } // Record the conformance. entry->Conformance = conformance; return conformance; }
llvm::GlobalVariable *emit() { auto entity = LinkEntity::forReflectionFieldDescriptor( NTD->getDeclaredType()->getCanonicalType()); auto section = IGM.getFieldTypeMetadataSectionName(); return ReflectionMetadataBuilder::emit(entity, section); }