File tree Expand file tree Collapse file tree 2 files changed +45
-6
lines changed Expand file tree Collapse file tree 2 files changed +45
-6
lines changed Original file line number Diff line number Diff line change @@ -1089,12 +1089,22 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const {
1089
1089
1090
1090
ConstraintFix *fix = nullptr ;
1091
1091
if (auto *GP = TypeVar->getImpl ().getGenericParameter ()) {
1092
- auto path = dstLocator->getPath ();
1093
- // Drop `generic parameter` locator element so that all missing
1094
- // generic parameters related to the same path can be coalesced later.
1095
- fix = DefaultGenericArgument::create (
1096
- cs, GP,
1097
- cs.getConstraintLocator (dstLocator->getAnchor (), path.drop_back ()));
1092
+ // If it is represetative for a key path root, let's emit a more
1093
+ // specific diagnostic.
1094
+ auto *keyPathRoot =
1095
+ cs.isRepresentativeFor (TypeVar, ConstraintLocator::KeyPathRoot);
1096
+ if (keyPathRoot) {
1097
+ fix = SpecifyKeyPathRootType::create (
1098
+ cs, keyPathRoot->getImpl ().getLocator ());
1099
+ } else {
1100
+ auto path = dstLocator->getPath ();
1101
+ // Drop `generic parameter` locator element so that all missing
1102
+ // generic parameters related to the same path can be coalesced later.
1103
+ fix = DefaultGenericArgument::create (
1104
+ cs, GP,
1105
+ cs.getConstraintLocator (dstLocator->getAnchor (),
1106
+ path.drop_back ()));
1107
+ }
1098
1108
} else if (TypeVar->getImpl ().isClosureParameterType ()) {
1099
1109
fix = SpecifyClosureParameterType::create (cs, dstLocator);
1100
1110
} else if (TypeVar->getImpl ().isClosureResultType ()) {
Original file line number Diff line number Diff line change @@ -3071,6 +3071,35 @@ class ConstraintSystem {
3071
3071
return typeVar->getImpl ().getRepresentative (getSavedBindings ());
3072
3072
}
3073
3073
3074
+ // / Finds if the given type variable is representative for a type
3075
+ // / variable which last locator path element is of the specified kind.
3076
+ // / If true returns the type variable which it is the representative for.
3077
+ TypeVariableType *
3078
+ isRepresentativeFor (TypeVariableType *typeVar,
3079
+ ConstraintLocator::PathElementKind kind) const {
3080
+ // We only attempt to look for this if type variable is
3081
+ // a representative.
3082
+ if (getRepresentative (typeVar) != typeVar)
3083
+ return nullptr ;
3084
+
3085
+ auto &CG = getConstraintGraph ();
3086
+ auto result = CG.lookupNode (typeVar);
3087
+ auto equivalence = result.first .getEquivalenceClass ();
3088
+ auto member = llvm::find_if (equivalence, [=](TypeVariableType *eq) {
3089
+ auto *loc = eq->getImpl ().getLocator ();
3090
+ if (!loc)
3091
+ return false ;
3092
+
3093
+ auto path = loc->getPath ();
3094
+ return !path.empty () && path.back ().getKind () == kind;
3095
+ });
3096
+
3097
+ if (member == equivalence.end ())
3098
+ return nullptr ;
3099
+
3100
+ return *member;
3101
+ }
3102
+
3074
3103
// / Gets the VarDecl associateed with resolvedOverload, and the type of the
3075
3104
// / storage wrapper if the decl has an associated storage wrapper.
3076
3105
Optional<std::pair<VarDecl *, Type>>
You can’t perform that action at this time.
0 commit comments