QualifiedType AmbiguousTypeParamType::forType(QualifiedType base, const Type * match, unsigned paramIndex) { base = dealias(base); match = dealias(match); switch (base->typeClass()) { case Type::Class: case Type::Struct: case Type::Interface: case Type::Protocol: { const CompositeType * ctBase = static_cast<const CompositeType *>(base.type()); if (const CompositeType * ctMatch = dyn_cast_or_null<CompositeType>(match)) { if (ctMatch != NULL) { base = ctBase->findBaseSpecializing(ctMatch); if (!base) { return QualifiedType(); } } if (paramIndex >= base->numTypeParams()) { return QualifiedType(); } else { return base->typeParam(paramIndex); } } return QualifiedType(); } case Type::NAddress: case Type::NArray: case Type::FlexibleArray: { if (paramIndex == 0 && (match == NULL || base->typeClass() == match->typeClass())) { return base->typeParam(0); } return QualifiedType(); } case Type::Tuple: { if (match != NULL || paramIndex >= base->numTypeParams()) { return QualifiedType(); } else { return base->typeParam(paramIndex); } } case Type::AmbiguousParameter: case Type::AmbiguousResult: case Type::AmbiguousTypeParam: case Type::AmbiguousPhi: case Type::Assignment: { QualifiedTypeSet expansion; base.expand(expansion); if (expansion.size() == 1) { return forType(*expansion.begin(), match, paramIndex); } return new AmbiguousTypeParamType(base, match, paramIndex); } default: return QualifiedType(); } }
bool SpCandidate::isMoreSpecific(const SpCandidate * other) const { const Template * tm = def_->templateSignature(); const Template * otm = other->def_->templateSignature(); if (tm->typeParams()->size() != otm->typeParams()->size()) { return false; } bool same = true; size_t numParams = tm->typeParams()->size(); for (size_t i = 0; i < numParams; ++i) { QualifiedType param = tm->typeParam(i); QualifiedType oparam = otm->typeParam(i); if (!TypeRelation::isEqual(param, oparam)) { same = false; if (!TypeRelation::isSubtype(param, oparam)) { if (oparam->typeClass() != Type::TypeVar) { return false; } // TODO: CanBind check here... } } } if (same) { // TODO A temporary kludge. if (!def_->hasUnboundTypeParams() && other->def_->hasUnboundTypeParams()) { return true; } } return !same; }