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();
  }
}
void AmbiguousTypeParamType::expandImpl(QualifiedTypeSet & out, unsigned qualifiers) const {
  QualifiedTypeSet baseExpansion;
  base_.expand(baseExpansion);
  for (QualifiedTypeSet::iterator it = baseExpansion.begin(); it != baseExpansion.end(); ++it) {
    QualifiedType ty = forType(*it, match_, paramIndex_);
    if (ty) {
      ty.expand(out, qualifiers);
    } else {
      out.insert(&BadType::instance);
    }
  }
}