diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 25d18bbc78da6..ecefad1941da1 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -2776,45 +2776,61 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs, auto &DE = cs.getASTContext().Diags; - llvm::SmallDenseMap> conflicts; + llvm::SmallDenseMap, 4> + genericParams; + // Consider only representative type variables shared across + // all of the solutions. + for (auto *typeVar : cs.getTypeVariables()) { + if (auto *GP = typeVar->getImpl().getGenericParameter()) { + auto *locator = typeVar->getImpl().getLocator(); + auto *repr = cs.getRepresentative(typeVar); + // If representative is another generic parameter let's + // use its generic parameter type instead of originator's, + // but it's possible that generic parameter is equated to + // some other type e.g. + // + // func foo(_: T) -> T {} + // + // In this case when reference to function `foo` is "opened" + // type variable representing `T` would be equated to + // type variable representing a result type of the reference. + if (auto *reprGP = repr->getImpl().getGenericParameter()) + GP = reprGP; + + genericParams[repr] = {GP, locator->getAnchor()->getLoc()}; + } + } - for (const auto &binding : solutions[0].typeBindings) { - auto *typeVar = binding.first; + llvm::SmallDenseMap, + SmallVector> + conflicts; - if (!typeVar->getImpl().getGenericParameter()) - continue; + for (const auto &entry : genericParams) { + auto *typeVar = entry.first; + auto GP = entry.second; llvm::SmallSetVector arguments; - arguments.insert(binding.second); - - if (!llvm::all_of(solutions.slice(1), [&](const Solution &solution) { - auto binding = solution.typeBindings.find(typeVar); - if (binding == solution.typeBindings.end()) - return false; - - // Contextual opaque result type is uniquely identified by - // declaration it's associated with, so we have to compare - // declarations instead of using pointer equality on such types. - if (auto *opaque = - binding->second->getAs()) { - auto *decl = opaque->getDecl(); - arguments.remove_if([&](Type argType) -> bool { - if (auto *otherOpaque = - argType->getAs()) { - return decl == otherOpaque->getDecl(); - } - return false; - }); + for (const auto &solution : solutions) { + auto type = solution.typeBindings.lookup(typeVar); + // Contextual opaque result type is uniquely identified by + // declaration it's associated with, so we have to compare + // declarations instead of using pointer equality on such types. + if (auto *opaque = type->getAs()) { + auto *decl = opaque->getDecl(); + arguments.remove_if([&](Type argType) -> bool { + if (auto *otherOpaque = argType->getAs()) { + return decl == otherOpaque->getDecl(); } + return false; + }); + } - arguments.insert(binding->second); - return true; - })) - continue; - - if (arguments.size() > 1) { - conflicts[typeVar].append(arguments.begin(), arguments.end()); + arguments.insert(type); } + + if (arguments.size() > 1) + conflicts[GP].append(arguments.begin(), arguments.end()); } auto getGenericTypeDecl = [&](ArchetypeType *archetype) -> ValueDecl * { @@ -2831,8 +2847,10 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs, bool diagnosed = false; for (auto &conflict : conflicts) { - auto *typeVar = conflict.first; - auto *locator = typeVar->getImpl().getLocator(); + SourceLoc loc; + GenericTypeParamType *GP; + + std::tie(GP, loc) = conflict.first; auto conflictingArguments = conflict.second; llvm::SmallString<64> arguments; @@ -2857,10 +2875,8 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs, }, [&OS] { OS << " vs. "; }); - auto *anchor = locator->getAnchor(); - DE.diagnose(anchor->getLoc(), - diag::conflicting_arguments_for_generic_parameter, - typeVar->getImpl().getGenericParameter(), OS.str()); + DE.diagnose(loc, diag::conflicting_arguments_for_generic_parameter, GP, + OS.str()); diagnosed = true; }