/// Check the generic parameters in the given generic parameter list (and its /// parent generic parameter lists) according to the given resolver. void TypeChecker::checkGenericParamList(GenericSignatureBuilder *builder, GenericParamList *genericParams, GenericSignature *parentSig, GenericTypeResolver *resolver) { // If there is a parent context, add the generic parameters and requirements // from that context. if (builder) builder->addGenericSignature(parentSig); // If there aren't any generic parameters at this level, we're done. if (!genericParams) return; assert(genericParams->size() > 0 && "Parsed an empty generic parameter list?"); // Determine where and how to perform name lookup for the generic // parameter lists and where clause. TypeResolutionOptions options; DeclContext *lookupDC = genericParams->begin()[0]->getDeclContext(); if (!lookupDC->isModuleScopeContext()) { assert((isa<GenericTypeDecl>(lookupDC) || isa<ExtensionDecl>(lookupDC) || isa<AbstractFunctionDecl>(lookupDC) || isa<SubscriptDecl>(lookupDC)) && "not a proper generic parameter context?"); options = TR_GenericSignature; } // First, add the generic parameters to the generic signature builder. // Do this before checking the inheritance clause, since it may // itself be dependent on one of these parameters. if (builder) { for (auto param : *genericParams) builder->addGenericParameter(param); } // Now, check the inheritance clauses of each parameter. for (auto param : *genericParams) { checkInheritanceClause(param, resolver); if (builder) builder->addGenericParameterRequirements(param); } // Visit each of the requirements, adding them to the builder. // Add the requirements clause to the builder, validating the types in // the requirements clause along the way. for (auto &req : genericParams->getRequirements()) { if (validateRequirement(genericParams->getWhereLoc(), req, lookupDC, options, resolver)) continue; if (builder && isErrorResult(builder->addRequirement(&req, lookupDC->getParentModule()))) req.setInvalid(); } }
SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const { // Anonymous functions have shared linkage. // FIXME: This should really be the linkage of the parent function. if (getAbstractClosureExpr()) return SILLinkage::Shared; // Native function-local declarations have shared linkage. // FIXME: @objc declarations should be too, but we currently have no way // of marking them "used" other than making them external. ValueDecl *d = getDecl(); DeclContext *moduleContext = d->getDeclContext(); while (!moduleContext->isModuleScopeContext()) { if (!isForeign && moduleContext->isLocalContext()) return SILLinkage::Shared; moduleContext = moduleContext->getParent(); } // Currying and calling convention thunks have shared linkage. if (isThunk()) // If a function declares a @_cdecl name, its native-to-foreign thunk // is exported with the visibility of the function. if (!isNativeToForeignThunk() || !d->getAttrs().hasAttribute<CDeclAttr>()) return SILLinkage::Shared; // Enum constructors are essentially the same as thunks, they are // emitted by need and have shared linkage. if (kind == Kind::EnumElement) return SILLinkage::Shared; // Declarations imported from Clang modules have shared linkage. const SILLinkage ClangLinkage = SILLinkage::Shared; if (isClangImported()) return ClangLinkage; // Declarations that were derived on behalf of types in Clang modules get // shared linkage. if (auto *FD = dyn_cast<FuncDecl>(d)) { if (auto derivedFor = FD->getDerivedForTypeDecl()) if (isa<ClangModuleUnit>(derivedFor->getModuleScopeContext())) return ClangLinkage; } // Otherwise, we have external linkage. switch (d->getEffectiveAccess()) { case Accessibility::Private: return (forDefinition ? SILLinkage::Private : SILLinkage::PrivateExternal); case Accessibility::Internal: return (forDefinition ? SILLinkage::Hidden : SILLinkage::HiddenExternal); default: return (forDefinition ? SILLinkage::Public : SILLinkage::PublicExternal); } }
SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const { // Anonymous functions have shared linkage. // FIXME: This should really be the linkage of the parent function. if (getAbstractClosureExpr()) return SILLinkage::Shared; // Native function-local declarations have shared linkage. // FIXME: @objc declarations should be too, but we currently have no way // of marking them "used" other than making them external. ValueDecl *d = getDecl(); DeclContext *moduleContext = d->getDeclContext(); while (!moduleContext->isModuleScopeContext()) { if (!isForeign && moduleContext->isLocalContext()) return SILLinkage::Shared; moduleContext = moduleContext->getParent(); } // Currying and calling convention thunks have shared linkage. if (isThunk()) // If a function declares a @_cdecl name, its native-to-foreign thunk // is exported with the visibility of the function. if (!isNativeToForeignThunk() || !d->getAttrs().hasAttribute<CDeclAttr>()) return SILLinkage::Shared; // Enum constructors are essentially the same as thunks, they are // emitted by need and have shared linkage. if (isEnumElement()) return SILLinkage::Shared; // Stored property initializers have hidden linkage, since they are // not meant to be used from outside of their module. if (isStoredPropertyInitializer()) return SILLinkage::Hidden; // Declarations imported from Clang modules have shared linkage. const SILLinkage ClangLinkage = SILLinkage::Shared; if (isClangImported()) return ClangLinkage; // Otherwise, we have external linkage. switch (d->getEffectiveAccess()) { case Accessibility::Private: case Accessibility::FilePrivate: return (forDefinition ? SILLinkage::Private : SILLinkage::PrivateExternal); case Accessibility::Internal: return (forDefinition ? SILLinkage::Hidden : SILLinkage::HiddenExternal); default: return (forDefinition ? SILLinkage::Public : SILLinkage::PublicExternal); } }
//===----------------------------------------------------------------------===// // Inheritance clause handling //===----------------------------------------------------------------------===// static std::tuple<TypeResolutionOptions, DeclContext *, MutableArrayRef<TypeLoc>> decomposeInheritedClauseDecl( llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl) { TypeResolutionOptions options; DeclContext *dc; MutableArrayRef<TypeLoc> inheritanceClause; if (auto typeDecl = decl.dyn_cast<TypeDecl *>()) { inheritanceClause = typeDecl->getInherited(); if (auto nominal = dyn_cast<NominalTypeDecl>(typeDecl)) { dc = nominal; options |= TypeResolutionFlags::GenericSignature; options |= TypeResolutionFlags::InheritanceClause; options |= TypeResolutionFlags::AllowUnavailableProtocol; } else { dc = typeDecl->getDeclContext(); if (isa<GenericTypeParamDecl>(typeDecl)) { // For generic parameters, we want name lookup to look at just the // signature of the enclosing entity. if (auto nominal = dyn_cast<NominalTypeDecl>(dc)) { dc = nominal; options |= TypeResolutionFlags::GenericSignature; } else if (auto ext = dyn_cast<ExtensionDecl>(dc)) { dc = ext; options |= TypeResolutionFlags::GenericSignature; } else if (auto func = dyn_cast<AbstractFunctionDecl>(dc)) { dc = func; options |= TypeResolutionFlags::GenericSignature; } else if (!dc->isModuleScopeContext()) { // Skip the generic parameter's context entirely. dc = dc->getParent(); } } } } else { auto ext = decl.get<ExtensionDecl *>(); inheritanceClause = ext->getInherited(); dc = ext; options |= TypeResolutionFlags::GenericSignature; options |= TypeResolutionFlags::InheritanceClause; options |= TypeResolutionFlags::AllowUnavailableProtocol; } return std::make_tuple(options, dc, inheritanceClause); }
/// Ensure that the outer generic parameters of the given generic /// context have been configured. static void configureOuterGenericParams(const GenericContext *dc) { auto genericParams = dc->getGenericParams(); // If we already configured the outer parameters, we're done. if (genericParams && genericParams->getOuterParameters()) return; DeclContext *outerDC = dc->getParent(); while (!outerDC->isModuleScopeContext()) { if (auto outerDecl = outerDC->getAsDecl()) { if (auto outerGenericDC = outerDecl->getAsGenericContext()) { if (genericParams) genericParams->setOuterParameters(outerGenericDC->getGenericParams()); configureOuterGenericParams(outerGenericDC); return; } } outerDC = outerDC->getParent(); } }
/// Check the generic parameters in the given generic parameter list (and its /// parent generic parameter lists) according to the given resolver. bool TypeChecker::checkGenericParamList(ArchetypeBuilder *builder, GenericParamList *genericParams, GenericSignature *parentSig, bool adoptArchetypes, GenericTypeResolver *resolver) { bool invalid = false; // If there is a parent context, add the generic parameters and requirements // from that context. if (builder) builder->addGenericSignature(parentSig, adoptArchetypes); // If there aren't any generic parameters at this level, we're done. if (!genericParams) return false; assert(genericParams->size() > 0 && "Parsed an empty generic parameter list?"); // Determine where and how to perform name lookup for the generic // parameter lists and where clause. TypeResolutionOptions options; DeclContext *lookupDC = genericParams->begin()[0]->getDeclContext(); if (!lookupDC->isModuleScopeContext()) { assert(isa<GenericTypeDecl>(lookupDC) || isa<ExtensionDecl>(lookupDC) || isa<AbstractFunctionDecl>(lookupDC) && "not a proper generic parameter context?"); options = TR_GenericSignature; } // First, set the depth of each generic parameter, and add them to the // archetype builder. Do this before checking the inheritance clause, // since it may itself be dependent on one of these parameters. unsigned depth = genericParams->getDepth(); for (auto param : *genericParams) { param->setDepth(depth); if (builder) { if (builder->addGenericParameter(param)) invalid = true; } } // Now, check the inheritance clauses of each parameter. for (auto param : *genericParams) { checkInheritanceClause(param, resolver); if (builder) { builder->addGenericParameterRequirements(param); // Infer requirements from the inherited types. for (const auto &inherited : param->getInherited()) { if (builder->inferRequirements(inherited, genericParams)) invalid = true; } } } // Visit each of the requirements, adding them to the builder. // Add the requirements clause to the builder, validating the types in // the requirements clause along the way. for (auto &req : genericParams->getRequirements()) { if (req.isInvalid()) continue; switch (req.getKind()) { case RequirementReprKind::TypeConstraint: { // Validate the types. if (validateType(req.getSubjectLoc(), lookupDC, options, resolver)) { invalid = true; req.setInvalid(); continue; } if (validateType(req.getConstraintLoc(), lookupDC, options, resolver)) { invalid = true; req.setInvalid(); continue; } // FIXME: Feels too early to perform this check. if (!req.getConstraint()->isExistentialType() && !req.getConstraint()->getClassOrBoundGenericClass()) { diagnose(genericParams->getWhereLoc(), diag::requires_conformance_nonprotocol, req.getSubjectLoc(), req.getConstraintLoc()); req.getConstraintLoc().setInvalidType(Context); invalid = true; req.setInvalid(); continue; } break; } case RequirementReprKind::SameType: if (validateType(req.getFirstTypeLoc(), lookupDC, options, resolver)) { invalid = true; req.setInvalid(); continue; } if (validateType(req.getSecondTypeLoc(), lookupDC, options, resolver)) { invalid = true; req.setInvalid(); continue; } break; } if (builder && builder->addRequirement(req)) { invalid = true; req.setInvalid(); } } return invalid; }
SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const { if (getAbstractClosureExpr()) { return isSerialized() ? SILLinkage::Shared : SILLinkage::Private; } // Add External to the linkage (e.g. Public -> PublicExternal) if this is a // declaration not a definition. auto maybeAddExternal = [&](SILLinkage linkage) { return forDefinition ? linkage : addExternalToLinkage(linkage); }; // Native function-local declarations have shared linkage. // FIXME: @objc declarations should be too, but we currently have no way // of marking them "used" other than making them external. ValueDecl *d = getDecl(); DeclContext *moduleContext = d->getDeclContext(); while (!moduleContext->isModuleScopeContext()) { if (!isForeign && moduleContext->isLocalContext()) { return isSerialized() ? SILLinkage::Shared : SILLinkage::Private; } moduleContext = moduleContext->getParent(); } // Enum constructors and curry thunks either have private or shared // linkage, dependings are essentially the same as thunks, they are // emitted by need and have shared linkage. if (isEnumElement() || isCurried) { switch (d->getEffectiveAccess()) { case AccessLevel::Private: case AccessLevel::FilePrivate: return maybeAddExternal(SILLinkage::Private); case AccessLevel::Internal: case AccessLevel::Public: case AccessLevel::Open: return SILLinkage::Shared; } } // Calling convention thunks have shared linkage. if (isForeignToNativeThunk()) return SILLinkage::Shared; // If a function declares a @_cdecl name, its native-to-foreign thunk // is exported with the visibility of the function. if (isNativeToForeignThunk() && !d->getAttrs().hasAttribute<CDeclAttr>()) return SILLinkage::Shared; // Declarations imported from Clang modules have shared linkage. if (isClangImported()) return SILLinkage::Shared; // Default argument generators of Public functions have PublicNonABI linkage // if the function was type-checked in Swift 4 mode. if (kind == SILDeclRef::Kind::DefaultArgGenerator) { if (isSerialized()) return maybeAddExternal(SILLinkage::PublicNonABI); } enum class Limit { /// No limit. None, /// The declaration is emitted on-demand; it should end up with internal /// or shared linkage. OnDemand, /// The declaration should never be made public. NeverPublic }; auto limit = Limit::None; // ivar initializers and destroyers are completely contained within the class // from which they come, and never get seen externally. if (isIVarInitializerOrDestroyer()) { limit = Limit::NeverPublic; } // Stored property initializers get the linkage of their containing type. if (isStoredPropertyInitializer()) { // Three cases: // // 1) Type is formally @_fixed_layout. Root initializers can be declared // @inlinable. The property initializer must only reference // public symbols, and is serialized, so we give it PublicNonABI linkage. // // 2) Type is not formally @_fixed_layout and the module is not resilient. // Root initializers can be declared @inlinable. This is the annoying // case. We give the initializer public linkage if the type is public. // // 3) Type is resilient. The property initializer is never public because // root initializers cannot be @inlinable. // // FIXME: Get rid of case 2 somehow. if (isSerialized()) return maybeAddExternal(SILLinkage::PublicNonABI); d = cast<NominalTypeDecl>(d->getDeclContext()); // FIXME: This should always be true. if (d->getDeclContext()->getParentModule()->getResilienceStrategy() == ResilienceStrategy::Resilient) limit = Limit::NeverPublic; } // The global addressor is never public for resilient globals. if (kind == Kind::GlobalAccessor) { if (cast<VarDecl>(d)->isResilient()) { limit = Limit::NeverPublic; } } // Forced-static-dispatch functions are created on-demand and have // at best shared linkage. if (auto fn = dyn_cast<FuncDecl>(d)) { if (fn->hasForcedStaticDispatch()) { limit = Limit::OnDemand; } } auto effectiveAccess = d->getEffectiveAccess(); // Private setter implementations for an internal storage declaration should // be internal as well, so that a dynamically-writable // keypath can be formed from other files. if (auto accessor = dyn_cast<AccessorDecl>(d)) { if (accessor->isSetter() && accessor->getStorage()->getEffectiveAccess() == AccessLevel::Internal) effectiveAccess = AccessLevel::Internal; } switch (effectiveAccess) { case AccessLevel::Private: case AccessLevel::FilePrivate: return maybeAddExternal(SILLinkage::Private); case AccessLevel::Internal: if (limit == Limit::OnDemand) return SILLinkage::Shared; return maybeAddExternal(SILLinkage::Hidden); case AccessLevel::Public: case AccessLevel::Open: if (limit == Limit::OnDemand) return SILLinkage::Shared; if (limit == Limit::NeverPublic) return maybeAddExternal(SILLinkage::Hidden); return maybeAddExternal(SILLinkage::Public); } llvm_unreachable("unhandled access"); }