static void initDocGenericParams(const Decl *D, DocEntityInfo &Info) { GenericParamList *GenParams = nullptr; if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) { GenParams = NTD->getGenericParams(); } else if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) { GenParams = AFD->getGenericParams(); } else if (auto *ExtD = dyn_cast<ExtensionDecl>(D)) { GenParams = ExtD->getGenericParams(); } if (!GenParams) return; for (auto *GP : GenParams->getParams()) { if (GP->isImplicit()) continue; DocGenericParam Param; Param.Name = GP->getNameStr(); if (!GP->getInherited().empty()) { llvm::raw_string_ostream OS(Param.Inherits); GP->getInherited()[0].getType().print(OS); } Info.GenericParams.push_back(Param); } for (auto &Req : GenParams->getRequirements()) { std::string ReqStr; llvm::raw_string_ostream OS(ReqStr); Req.printAsWritten(OS); OS.flush(); Info.GenericRequirements.push_back(std::move(ReqStr)); } }
void TypeChecker::markInvalidGenericSignature(ValueDecl *VD) { GenericParamList *genericParams; if (auto *AFD = dyn_cast<AbstractFunctionDecl>(VD)) genericParams = AFD->getGenericParams(); else genericParams = cast<GenericTypeDecl>(VD)->getGenericParams(); // If there aren't any generic parameters at this level, we're done. if (genericParams == nullptr) return; DeclContext *DC = VD->getDeclContext(); ArchetypeBuilder builder = createArchetypeBuilder(DC->getParentModule()); if (auto sig = DC->getGenericSignatureOfContext()) builder.addGenericSignature(sig, true); // Visit each of the generic parameters. for (auto param : *genericParams) builder.addGenericParameter(param); // Wire up the archetypes. for (auto GP : *genericParams) GP->setArchetype(builder.getArchetype(GP)); genericParams->setAllArchetypes( Context.AllocateCopy(builder.getAllArchetypes())); }
GenericTypeParamType *DeclContext::getProtocolSelfType() const { assert(getSelfProtocolDecl() && "not a protocol"); GenericParamList *genericParams; if (auto proto = dyn_cast<ProtocolDecl>(this)) { genericParams = proto->getGenericParams(); } else { genericParams = cast<ExtensionDecl>(this)->getGenericParams(); } if (genericParams == nullptr) return nullptr; return genericParams->getParams().front() ->getDeclaredInterfaceType() ->castTo<GenericTypeParamType>(); }
ParserResult<GenericParamList> Parser::maybeParseGenericParams() { if (!startsWithLess(Tok)) return nullptr; if (!isInSILMode()) return parseGenericParameters(); // In SIL mode, we can have multiple generic parameter lists, with the // first one being the outmost generic parameter list. GenericParamList *gpl = nullptr, *outer_gpl = nullptr; do { gpl = parseGenericParameters().getPtrOrNull(); if (!gpl) return nullptr; if (outer_gpl) gpl->setOuterParameters(outer_gpl); outer_gpl = gpl; } while (startsWithLess(Tok)); return makeParserResult(gpl); }
static Substitution getSimpleSubstitution(GenericParamList &generics, CanType typeArg) { assert(generics.getParams().size() == 1); auto typeParamDecl = generics.getParams().front(); return Substitution{typeParamDecl->getArchetype(), typeArg, {}}; }
/// parseType /// type: /// attribute-list type-function /// attribute-list type-array /// /// type-function: /// type-simple '->' type /// ParserResult<TypeRepr> Parser::parseType(Diag<> MessageID, bool HandleCodeCompletion) { // Parse attributes. TypeAttributes attrs; parseTypeAttributeList(attrs); // Parse Generic Parameters. Generic Parameters are visible in the function // body. GenericParamList *generics = nullptr; if (isInSILMode()) { generics = maybeParseGenericParams().getPtrOrNull(); } ParserResult<TypeRepr> ty = parseTypeSimple(MessageID, HandleCodeCompletion); if (ty.hasCodeCompletion()) return makeParserCodeCompletionResult<TypeRepr>(); if (ty.isNull()) return nullptr; // Parse a throws specifier. 'throw' is probably a typo for 'throws', // but in local contexts we could just be at the end of a statement, // so we need to check for the arrow. ParserPosition beforeThrowsPos; SourceLoc throwsLoc; bool rethrows = false; if (Tok.isAny(tok::kw_throws, tok::kw_rethrows) || (Tok.is(tok::kw_throw) && peekToken().is(tok::arrow))) { if (Tok.is(tok::kw_throw)) { diagnose(Tok.getLoc(), diag::throw_in_function_type) .fixItReplace(Tok.getLoc(), "throws"); } beforeThrowsPos = getParserPosition(); rethrows = Tok.is(tok::kw_rethrows); throwsLoc = consumeToken(); } // Handle type-function if we have an arrow. SourceLoc arrowLoc; if (consumeIf(tok::arrow, arrowLoc)) { ParserResult<TypeRepr> SecondHalf = parseType(diag::expected_type_function_result); if (SecondHalf.hasCodeCompletion()) return makeParserCodeCompletionResult<TypeRepr>(); if (SecondHalf.isNull()) return nullptr; if (rethrows) { // 'rethrows' is only allowed on function declarations for now. diagnose(throwsLoc, diag::rethrowing_function_type); } auto fnTy = new (Context) FunctionTypeRepr(generics, ty.get(), throwsLoc, arrowLoc, SecondHalf.get()); return makeParserResult(applyAttributeToType(fnTy, attrs)); } else if (throwsLoc.isValid()) { // Don't consume 'throws', so we can emit a more useful diagnostic when // parsing a function decl. restoreParserPosition(beforeThrowsPos); return ty; } // Only function types may be generic. if (generics) { auto brackets = generics->getSourceRange(); diagnose(brackets.Start, diag::generic_non_function); } // Parse legacy array types for migration. while (ty.isNonNull() && !Tok.isAtStartOfLine()) { if (Tok.is(tok::l_square)) { ty = parseTypeArray(ty.get()); } else { break; } } if (ty.isNonNull() && !ty.hasCodeCompletion()) { ty = makeParserResult(applyAttributeToType(ty.get(), attrs)); } return ty; }
static void lookupVisibleDeclsImpl(VisibleDeclConsumer &Consumer, const DeclContext *DC, LazyResolver *TypeResolver, bool IncludeTopLevel, SourceLoc Loc) { const ModuleDecl &M = *DC->getParentModule(); const SourceManager &SM = DC->getASTContext().SourceMgr; auto Reason = DeclVisibilityKind::MemberOfCurrentNominal; // If we are inside of a method, check to see if there are any ivars in scope, // and if so, whether this is a reference to one of them. while (!DC->isModuleScopeContext()) { GenericParamList *GenericParams = nullptr; Type ExtendedType; auto LS = LookupState::makeUnqualified(); // Skip initializer contexts, we will not find any declarations there. if (isa<Initializer>(DC)) { DC = DC->getParent(); LS = LS.withOnMetatype(); } // We don't look for generic parameters if we are in the context of a // nominal type: they will be looked up anyways via `lookupVisibleMemberDecls`. if (DC && !isa<NominalTypeDecl>(DC)) { if (auto *decl = DC->getAsDecl()) { if (auto GC = decl->getAsGenericContext()) { auto params = GC->getGenericParams(); namelookup::FindLocalVal(SM, Loc, Consumer).checkGenericParams(params); } } } if (auto *SE = dyn_cast<SubscriptDecl>(DC)) { ExtendedType = SE->getDeclContext()->getSelfTypeInContext(); DC = DC->getParent(); } else if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC)) { // Look for local variables; normally, the parser resolves these // for us, but it can't do the right thing inside local types. // FIXME: when we can parse and typecheck the function body partially for // code completion, AFD->getBody() check can be removed. if (Loc.isValid() && AFD->getBody()) { namelookup::FindLocalVal(SM, Loc, Consumer).visit(AFD->getBody()); } if (auto *P = AFD->getImplicitSelfDecl()) { namelookup::FindLocalVal(SM, Loc, Consumer).checkValueDecl( const_cast<ParamDecl *>(P), DeclVisibilityKind::FunctionParameter); } namelookup::FindLocalVal(SM, Loc, Consumer).checkParameterList( AFD->getParameters()); GenericParams = AFD->getGenericParams(); if (AFD->getDeclContext()->isTypeContext()) { ExtendedType = AFD->getDeclContext()->getSelfTypeInContext(); DC = DC->getParent(); if (auto *FD = dyn_cast<FuncDecl>(AFD)) if (FD->isStatic()) ExtendedType = MetatypeType::get(ExtendedType); } } else if (auto CE = dyn_cast<ClosureExpr>(DC)) { if (Loc.isValid()) { namelookup::FindLocalVal(SM, Loc, Consumer).visit(CE->getBody()); if (auto P = CE->getParameters()) { namelookup::FindLocalVal(SM, Loc, Consumer).checkParameterList(P); } } } else if (auto ED = dyn_cast<ExtensionDecl>(DC)) { ExtendedType = ED->getSelfTypeInContext(); } else if (auto ND = dyn_cast<NominalTypeDecl>(DC)) { ExtendedType = ND->getSelfTypeInContext(); } // If we're inside a function context, we've already moved to // the parent DC, so we have to check the function's generic // parameters first. if (GenericParams) { namelookup::FindLocalVal localVal(SM, Loc, Consumer); localVal.checkGenericParams(GenericParams); } // Check the generic parameters of our context. GenericParamList *dcGenericParams = nullptr; if (auto nominal = dyn_cast<NominalTypeDecl>(DC)) dcGenericParams = nominal->getGenericParams(); else if (auto ext = dyn_cast<ExtensionDecl>(DC)) dcGenericParams = ext->getGenericParams(); else if (auto subscript = dyn_cast<SubscriptDecl>(DC)) dcGenericParams = subscript->getGenericParams(); while (dcGenericParams) { namelookup::FindLocalVal localVal(SM, Loc, Consumer); localVal.checkGenericParams(dcGenericParams); dcGenericParams = dcGenericParams->getOuterParameters(); } if (ExtendedType) ::lookupVisibleMemberDecls(ExtendedType, Consumer, DC, LS, Reason, TypeResolver, nullptr); DC = DC->getParent(); Reason = DeclVisibilityKind::MemberOfOutsideNominal; } SmallVector<ModuleDecl::ImportedModule, 8> extraImports; if (auto SF = dyn_cast<SourceFile>(DC)) { if (Loc.isValid()) { // Look for local variables in top-level code; normally, the parser // resolves these for us, but it can't do the right thing for // local types. namelookup::FindLocalVal(SM, Loc, Consumer).checkSourceFile(*SF); } if (IncludeTopLevel) { auto &cached = SF->getCachedVisibleDecls(); if (!cached.empty()) { for (auto result : cached) Consumer.foundDecl(result, DeclVisibilityKind::VisibleAtTopLevel); return; } SF->getImportedModules(extraImports, ModuleDecl::ImportFilter::Private); } } if (IncludeTopLevel) { using namespace namelookup; SmallVector<ValueDecl *, 0> moduleResults; auto &mutableM = const_cast<ModuleDecl&>(M); lookupVisibleDeclsInModule(&mutableM, {}, moduleResults, NLKind::UnqualifiedLookup, ResolutionKind::Overloadable, TypeResolver, DC, extraImports); for (auto result : moduleResults) Consumer.foundDecl(result, DeclVisibilityKind::VisibleAtTopLevel); if (auto SF = dyn_cast<SourceFile>(DC)) SF->cacheVisibleDecls(std::move(moduleResults)); } }
static Substitution getSimpleSubstitution(GenericParamList &generics, CanType typeArg) { assert(generics.getParams().size() == 1); return Substitution{typeArg, {}}; }