@@ -12199,17 +12199,15 @@ ConstraintSystem::simplifyKeyPathConstraint(
1219912199 ConstraintLocatorBuilder locator) {
1220012200 auto subflags = getDefaultDecompositionOptions(flags);
1220112201 // The constraint ought to have been anchored on a KeyPathExpr.
12202- auto keyPath = castToExpr<KeyPathExpr>(locator.getBaseLocator()-> getAnchor());
12202+ auto keyPath = castToExpr<KeyPathExpr>(locator.getAnchor());
1220312203 keyPathTy = getFixedTypeRecursive(keyPathTy, /*want rvalue*/ true);
12204- bool definitelyFunctionType = false;
12205- bool definitelyKeyPathType = false;
1220612204 bool resolveAsMultiArgFuncFix = false;
1220712205
1220812206 auto formUnsolved = [&]() -> SolutionKind {
1220912207 if (flags.contains(TMF_GenerateConstraints)) {
1221012208 addUnsolvedConstraint(Constraint::create(
1221112209 *this, ConstraintKind::KeyPath, keyPathTy, rootTy, valueTy,
12212- locator.getBaseLocator( ), componentTypeVars));
12210+ getConstraintLocator(locator ), componentTypeVars));
1221312211 return SolutionKind::Solved;
1221412212 }
1221512213 return SolutionKind::Unsolved;
@@ -12218,25 +12216,18 @@ ConstraintSystem::simplifyKeyPathConstraint(
1221812216 if (keyPathTy->isTypeVariableOrMember())
1221912217 return formUnsolved();
1222012218
12221- auto tryMatchRootAndValueFromType = [&](Type type,
12222- bool allowPartial = true) -> bool {
12219+ auto tryMatchRootAndValueFromType = [&](Type type) -> bool {
1222312220 Type boundRoot = Type(), boundValue = Type();
1222412221
1222512222 if (auto bgt = type->getAs<BoundGenericType>()) {
12226- definitelyKeyPathType = true;
12227-
1222812223 // We can get root and value from a concrete key path type.
1222912224 if (bgt->isKeyPath() ||
1223012225 bgt->isWritableKeyPath() ||
1223112226 bgt->isReferenceWritableKeyPath()) {
1223212227 boundRoot = bgt->getGenericArgs()[0];
1223312228 boundValue = bgt->getGenericArgs()[1];
12234- } else if (bgt->isPartialKeyPath()) {
12235- if (!allowPartial)
12236- return false;
12237-
12238- // We can still get the root from a PartialKeyPath.
12239- boundRoot = bgt->getGenericArgs()[0];
12229+ } else {
12230+ return false;
1224012231 }
1224112232 }
1224212233
@@ -12247,13 +12238,11 @@ ConstraintSystem::simplifyKeyPathConstraint(
1224712238
1224812239 resolveAsMultiArgFuncFix = true;
1224912240 auto *fix = AllowMultiArgFuncKeyPathMismatch::create(
12250- *this, fnTy, locator.getBaseLocator( ));
12241+ *this, fnTy, getConstraintLocator(locator ));
1225112242 // Pretend the keypath type got resolved and move on.
1225212243 return !recordFix(fix);
1225312244 }
1225412245
12255- definitelyFunctionType = true;
12256-
1225712246 // Match up the root and value types to the function's param and return
1225812247 // types. Note that we're using the type of the parameter as referenced
1225912248 // from inside the function body as we'll be transforming the code into:
@@ -12300,192 +12289,66 @@ ConstraintSystem::simplifyKeyPathConstraint(
1230012289 // If the root type has been bound to a hole, we cannot infer it.
1230112290 if (getFixedTypeRecursive(rootTy, /*wantRValue*/ true)->isPlaceholder())
1230212291 return SolutionKind::Solved;
12303-
12304- // If we have e.g a missing member somewhere, a component type variable
12305- // would either be marked as a potential hole or would have a fix.
12306- if (llvm::any_of(componentTypeVars, [&](TypeVariableType *tv) {
12307- auto *locator = tv->getImpl().getLocator();
12308-
12309- // Result type of a component could be bound to a contextual
12310- // (concrete) type if it's the last component in the chain,
12311- // so the only way to detect errors is to check for fixes.
12312- if (locator->isForKeyPathComponentResult()) {
12313- auto path = locator->getPath();
12314- auto *componentLoc =
12315- getConstraintLocator(locator->getAnchor(), path.drop_back());
12316-
12317- if (hasFixFor(componentLoc, FixKind::DefineMemberBasedOnUse) ||
12318- hasFixFor(componentLoc, FixKind::UnwrapOptionalBase) ||
12319- hasFixFor(componentLoc,
12320- FixKind::UnwrapOptionalBaseWithOptionalResult))
12321- return true;
12322- }
12323-
12324- // If something inside of a component is marked as a hole,
12325- // let's consider while component to be invalid.
12326- return locator->isInKeyPathComponent() &&
12327- tv->getImpl().canBindToHole();
12328- })) {
12329- (void)tryMatchRootAndValueFromType(keyPathTy);
12330- return SolutionKind::Solved;
12331- }
1233212292 }
1233312293
1233412294 // If we're fixed to a bound generic type, trying harvesting context from it.
1233512295 // However, we don't want a solution that fixes the expression type to
1233612296 // PartialKeyPath; we'd rather that be represented using an upcast conversion.
12337- if (!tryMatchRootAndValueFromType(keyPathTy, /*allowPartial=*/false ))
12297+ if (!tryMatchRootAndValueFromType(keyPathTy))
1233812298 return SolutionKind::Error;
1233912299
1234012300 // If we fix this keypath as `AllowMultiArgFuncKeyPathMismatch`, just proceed
1234112301 if (resolveAsMultiArgFuncFix)
1234212302 return SolutionKind::Solved;
1234312303
12344- // See if we resolved overloads for all the components involved.
12345- enum {
12346- ReadOnly,
12347- Writable,
12348- ReferenceWritable
12349- } capability = Writable;
12304+ bool isValid;
12305+ llvm::Optional<KeyPathCapability> capability;
1235012306
12351- bool anyComponentsUnresolved = false;
12352- bool didOptionalChain = false;
12307+ std::tie(isValid, capability) = inferKeyPathLiteralCapability(keyPath);
1235312308
12354- for (unsigned i : indices(keyPath->getComponents())) {
12355- auto &component = keyPath->getComponents()[i];
12356-
12357- switch (component.getKind()) {
12358- case KeyPathExpr::Component::Kind::Invalid:
12359- case KeyPathExpr::Component::Kind::Identity:
12360- break;
12309+ // If key path is invalid, let's not don't attempt match capabilities.
12310+ if (!isValid)
12311+ return shouldAttemptFixes() ? SolutionKind::Solved : SolutionKind::Error;
1236112312
12362- case KeyPathExpr::Component::Kind::CodeCompletion: {
12363- anyComponentsUnresolved = true;
12364- capability = ReadOnly;
12365- break;
12366- }
12367- case KeyPathExpr::Component::Kind::Property:
12368- case KeyPathExpr::Component::Kind::Subscript:
12369- case KeyPathExpr::Component::Kind::UnresolvedProperty:
12370- case KeyPathExpr::Component::Kind::UnresolvedSubscript: {
12371- auto *componentLoc = getConstraintLocator(
12372- locator.withPathElement(LocatorPathElt::KeyPathComponent(i)));
12373- auto *calleeLoc = getCalleeLocator(componentLoc);
12374- auto overload = findSelectedOverloadFor(calleeLoc);
12375-
12376- // If no choice was made, leave the constraint unsolved. But when
12377- // generating constraints, we may already have enough information
12378- // to determine whether the result will be a function type vs BGT KeyPath
12379- // type, so continue through components to create new constraint at the
12380- // end.
12381- if (!overload) {
12382- if (flags.contains(TMF_GenerateConstraints)) {
12383- anyComponentsUnresolved = true;
12384- continue;
12385- }
12386- return SolutionKind::Unsolved;
12387- }
12388-
12389- // tuple elements do not change the capability of the key path
12390- auto choice = overload->choice;
12391- if (choice.getKind() == OverloadChoiceKind::TupleIndex) {
12392- continue;
12393- }
12394-
12395- // Discarded unsupported non-decl member lookups.
12396- if (!choice.isDecl()) {
12397- return SolutionKind::Error;
12398- }
12399-
12400- auto storage = dyn_cast<AbstractStorageDecl>(choice.getDecl());
12401-
12402- if (hasFixFor(calleeLoc, FixKind::AllowInvalidRefInKeyPath)) {
12403- return shouldAttemptFixes() ? SolutionKind::Solved
12404- : SolutionKind::Error;
12405- }
12406-
12407- if (!storage)
12408- return SolutionKind::Error;
12409-
12410- if (isReadOnlyKeyPathComponent(storage, component.getLoc())) {
12411- capability = ReadOnly;
12412- continue;
12413- }
12414-
12415- // A nonmutating setter indicates a reference-writable base.
12416- if (!storage->isSetterMutating()) {
12417- capability = ReferenceWritable;
12418- continue;
12419- }
12420-
12421- // Otherwise, the key path maintains its current capability.
12422- break;
12423- }
12424-
12425- case KeyPathExpr::Component::Kind::OptionalChain:
12426- didOptionalChain = true;
12427- break;
12428-
12429- case KeyPathExpr::Component::Kind::OptionalForce:
12430- // Forcing an optional preserves its lvalue-ness.
12431- break;
12432-
12433- case KeyPathExpr::Component::Kind::OptionalWrap:
12434- // An optional chain should already have been recorded.
12435- assert(didOptionalChain);
12436- break;
12437-
12438- case KeyPathExpr::Component::Kind::TupleElement:
12439- llvm_unreachable("not implemented");
12440- break;
12441- case KeyPathExpr::Component::Kind::DictionaryKey:
12442- llvm_unreachable("DictionaryKey only valid in #keyPath");
12443- break;
12444- }
12445- }
12446-
12447- // Optional chains force the entire key path to be read-only.
12448- if (didOptionalChain)
12449- capability = ReadOnly;
12313+ // If key path is valid but not yet sufficiently resolved, let's delay
12314+ // capability checking.
12315+ if (!capability)
12316+ return formUnsolved();
1245012317
1245112318 // Resolve the type.
1245212319 NominalTypeDecl *kpDecl;
12453- switch (capability) {
12454- case ReadOnly:
12320+ switch (* capability) {
12321+ case KeyPathCapability:: ReadOnly:
1245512322 kpDecl = getASTContext().getKeyPathDecl();
1245612323 break;
1245712324
12458- case Writable:
12325+ case KeyPathCapability:: Writable:
1245912326 kpDecl = getASTContext().getWritableKeyPathDecl();
1246012327 break;
1246112328
12462- case ReferenceWritable:
12329+ case KeyPathCapability:: ReferenceWritable:
1246312330 kpDecl = getASTContext().getReferenceWritableKeyPathDecl();
1246412331 break;
1246512332 }
12466-
12333+
1246712334 // FIXME: Allow the type to be upcast if the type system has a concrete
1246812335 // KeyPath type assigned to the expression already.
1246912336 if (auto keyPathBGT = keyPathTy->getAs<BoundGenericType>()) {
1247012337 if (keyPathBGT->isKeyPath())
1247112338 kpDecl = getASTContext().getKeyPathDecl();
12472- else if (keyPathBGT->isWritableKeyPath() && capability >= Writable)
12339+ else if (keyPathBGT->isWritableKeyPath() &&
12340+ *capability >= KeyPathCapability::Writable)
1247312341 kpDecl = getASTContext().getWritableKeyPathDecl();
1247412342 }
1247512343
12476- auto loc = locator.getBaseLocator();
12477- if (definitelyFunctionType) {
12344+ if (keyPathTy->is<FunctionType>()) {
1247812345 increaseScore(SK_FunctionConversion, locator);
1247912346 return SolutionKind::Solved;
12480- } else if (!anyComponentsUnresolved ||
12481- (definitelyKeyPathType && capability == ReadOnly)) {
12482- auto resolvedKPTy =
12483- BoundGenericType::get(kpDecl, nullptr, {rootTy, valueTy});
12484- return matchTypes(resolvedKPTy, keyPathTy, ConstraintKind::Bind, subflags,
12485- loc);
1248612347 }
1248712348
12488- return formUnsolved();
12349+ auto resolvedKPTy = BoundGenericType::get(kpDecl, nullptr, {rootTy, valueTy});
12350+ return matchTypes(resolvedKPTy, keyPathTy, ConstraintKind::Bind, subflags,
12351+ locator);
1248912352}
1249012353
1249112354ConstraintSystem::SolutionKind
0 commit comments