void DeclarationAnalyzer::visitStruct(const StructDefPtr& node) { TypePtr type = defineType(node); SCOPED_SET(ctx->currentType, type); visitDeclaration(node); //prepare default initializers this->prepareDefaultInitializers(type); //Type verification and typealias inference for(auto entry : type->getAllParents()) { TypePtr parent = entry.first; if(parent->getCategory() != Type::Protocol || !(parent->containsAssociatedType() || parent->containsSelfType())) continue; //this parent is a protocol that contains associated type, now validate protocol's methods and infer the types out std::map<std::wstring, TypePtr> associatedTypes; //collect all defined associated types for(auto entry : parent->getAssociatedTypes()) { TypePtr type = entry.second->unwrap(); if(type->getCategory() != Type::Alias) associatedTypes.insert(make_pair(entry.first, type)); } if(parent->containsSelfType()) associatedTypes.insert(make_pair(L"Self", type)); for(const FunctionOverloadedSymbolPtr& funcs : parent->getDeclaredFunctions()) { for(const FunctionSymbolPtr& expectedFunc : *funcs) { TypePtr expectedType = expectedFunc->getType(); assert(expectedType != nullptr); bool matched = false; //get all methods with the same name, and check their signature one by one vector<SymbolPtr> funcs; bool staticMember = expectedFunc->hasFlags(SymbolFlagStatic); semanticAnalyzer->getMethodsFromType(type, expectedFunc->getName(), (MemberFilter)((staticMember ? FilterStaticMember : 0) | (FilterLookupInExtension | FilterRecursive)), funcs); for(const SymbolPtr& func : funcs) { TypePtr actualType = func->getType(); assert(actualType != nullptr); if(expectedType->canSpecializeTo(actualType, associatedTypes)) { matched = true; break; } } if(!matched) { //no matched function error(node, Errors::E_TYPE_DOES_NOT_CONFORM_TO_PROTOCOL_UNIMPLEMENTED_FUNCTION_3, type->getName(), parent->getName(), expectedFunc->getName()); return; } } } //now make types infered above visible for(auto entry : associatedTypes) { if(entry.first == L"Self") continue; static_pointer_cast<TypeBuilder>(type)->addMember(entry.first, entry.second); } } verifyProtocolConform(type); validateDeclarationModifiers(node); visitImplementation(node); }