Skip to content

Commit 9ce4b60

Browse files
authored
Merge pull request #30297 from xedin/diagnose-gp-conflicts-for-reprs
[ConstraintSystem] Diagnose argument conflicts only for "representati…
2 parents 4715d68 + 4a06b13 commit 9ce4b60

File tree

1 file changed

+54
-38
lines changed

1 file changed

+54
-38
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 54 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2776,45 +2776,61 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs,
27762776

27772777
auto &DE = cs.getASTContext().Diags;
27782778

2779-
llvm::SmallDenseMap<TypeVariableType *, SmallVector<Type, 4>> conflicts;
2779+
llvm::SmallDenseMap<TypeVariableType *,
2780+
std::pair<GenericTypeParamType *, SourceLoc>, 4>
2781+
genericParams;
2782+
// Consider only representative type variables shared across
2783+
// all of the solutions.
2784+
for (auto *typeVar : cs.getTypeVariables()) {
2785+
if (auto *GP = typeVar->getImpl().getGenericParameter()) {
2786+
auto *locator = typeVar->getImpl().getLocator();
2787+
auto *repr = cs.getRepresentative(typeVar);
2788+
// If representative is another generic parameter let's
2789+
// use its generic parameter type instead of originator's,
2790+
// but it's possible that generic parameter is equated to
2791+
// some other type e.g.
2792+
//
2793+
// func foo<T>(_: T) -> T {}
2794+
//
2795+
// In this case when reference to function `foo` is "opened"
2796+
// type variable representing `T` would be equated to
2797+
// type variable representing a result type of the reference.
2798+
if (auto *reprGP = repr->getImpl().getGenericParameter())
2799+
GP = reprGP;
2800+
2801+
genericParams[repr] = {GP, locator->getAnchor()->getLoc()};
2802+
}
2803+
}
27802804

2781-
for (const auto &binding : solutions[0].typeBindings) {
2782-
auto *typeVar = binding.first;
2805+
llvm::SmallDenseMap<std::pair<GenericTypeParamType *, SourceLoc>,
2806+
SmallVector<Type, 4>>
2807+
conflicts;
27832808

2784-
if (!typeVar->getImpl().getGenericParameter())
2785-
continue;
2809+
for (const auto &entry : genericParams) {
2810+
auto *typeVar = entry.first;
2811+
auto GP = entry.second;
27862812

27872813
llvm::SmallSetVector<Type, 4> arguments;
2788-
arguments.insert(binding.second);
2789-
2790-
if (!llvm::all_of(solutions.slice(1), [&](const Solution &solution) {
2791-
auto binding = solution.typeBindings.find(typeVar);
2792-
if (binding == solution.typeBindings.end())
2793-
return false;
2794-
2795-
// Contextual opaque result type is uniquely identified by
2796-
// declaration it's associated with, so we have to compare
2797-
// declarations instead of using pointer equality on such types.
2798-
if (auto *opaque =
2799-
binding->second->getAs<OpaqueTypeArchetypeType>()) {
2800-
auto *decl = opaque->getDecl();
2801-
arguments.remove_if([&](Type argType) -> bool {
2802-
if (auto *otherOpaque =
2803-
argType->getAs<OpaqueTypeArchetypeType>()) {
2804-
return decl == otherOpaque->getDecl();
2805-
}
2806-
return false;
2807-
});
2814+
for (const auto &solution : solutions) {
2815+
auto type = solution.typeBindings.lookup(typeVar);
2816+
// Contextual opaque result type is uniquely identified by
2817+
// declaration it's associated with, so we have to compare
2818+
// declarations instead of using pointer equality on such types.
2819+
if (auto *opaque = type->getAs<OpaqueTypeArchetypeType>()) {
2820+
auto *decl = opaque->getDecl();
2821+
arguments.remove_if([&](Type argType) -> bool {
2822+
if (auto *otherOpaque = argType->getAs<OpaqueTypeArchetypeType>()) {
2823+
return decl == otherOpaque->getDecl();
28082824
}
2825+
return false;
2826+
});
2827+
}
28092828

2810-
arguments.insert(binding->second);
2811-
return true;
2812-
}))
2813-
continue;
2814-
2815-
if (arguments.size() > 1) {
2816-
conflicts[typeVar].append(arguments.begin(), arguments.end());
2829+
arguments.insert(type);
28172830
}
2831+
2832+
if (arguments.size() > 1)
2833+
conflicts[GP].append(arguments.begin(), arguments.end());
28182834
}
28192835

28202836
auto getGenericTypeDecl = [&](ArchetypeType *archetype) -> ValueDecl * {
@@ -2831,8 +2847,10 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs,
28312847

28322848
bool diagnosed = false;
28332849
for (auto &conflict : conflicts) {
2834-
auto *typeVar = conflict.first;
2835-
auto *locator = typeVar->getImpl().getLocator();
2850+
SourceLoc loc;
2851+
GenericTypeParamType *GP;
2852+
2853+
std::tie(GP, loc) = conflict.first;
28362854
auto conflictingArguments = conflict.second;
28372855

28382856
llvm::SmallString<64> arguments;
@@ -2857,10 +2875,8 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs,
28572875
},
28582876
[&OS] { OS << " vs. "; });
28592877

2860-
auto *anchor = locator->getAnchor();
2861-
DE.diagnose(anchor->getLoc(),
2862-
diag::conflicting_arguments_for_generic_parameter,
2863-
typeVar->getImpl().getGenericParameter(), OS.str());
2878+
DE.diagnose(loc, diag::conflicting_arguments_for_generic_parameter, GP,
2879+
OS.str());
28642880
diagnosed = true;
28652881
}
28662882

0 commit comments

Comments
 (0)