don't. switch (choice1.getKind()) { case OverloadChoiceKind::TupleIndex: case OverloadChoiceKind::MaterializePack: case OverloadChoiceKind::ExtractFunctionIsolation: continue; case OverloadChoiceKind::KeyPathApplication: llvm_unreachable("Never considered different"); case OverloadChoiceKind::DeclViaDynamic: case OverloadChoiceKind::Decl: case OverloadChoiceKind::DeclViaBridge: case OverloadChoiceKind::DeclViaUnwrappedOptional: case OverloadChoiceKind::DynamicMemberLookup: case OverloadChoiceKind::KeyPathDynamicMemberLookup: break; } // We don't apply some ranking rules to overloads found through dynamic // lookup in order to keep a few potentially ill-formed cases ambiguous. bool isDynamicOverloadComparison = choice1.getKind() == OverloadChoiceKind::DeclViaDynamic && choice2.getKind() == OverloadChoiceKind::DeclViaDynamic; // Determine whether one declaration is more specialized than the other. bool firstAsSpecializedAs = false; bool secondAsSpecializedAs = false; if (isDeclAsSpecializedAs(cs.DC, decl1, decl2, isDynamicOverloadComparison, /*allowMissingConformances=*/false)) { score1 += weight; firstAsSpecializedAs = true; } if (isDeclAsSpecializedAs(cs.DC, decl2, decl1, isDynamicOverloadComparison, /*allowMissingConformances=*/false)) { score2 += weight; secondAsSpecializedAs = true; } // If each is as specialized as the other, and both are constructors, // check the constructor kind. if (firstAsSpecializedAs && secondAsSpecializedAs) { if (auto ctor1 = dyn_cast<ConstructorDecl>(decl1)) { if (auto ctor2 = dyn_cast<ConstructorDecl>(decl2)) { if (ctor1->getInitKind() != ctor2->getInitKind()) { if (ctor1->getInitKind() < ctor2->getInitKind()) score1 += weight; else score2 += weight; } else if (ctor1->getInitKind() == CtorInitializerKind::Convenience) { // If both are convenience initializers, and the instance type of // one is a subtype of the other's, favor the subtype constructor. auto resType1 = ctor1->mapTypeIntoContext( ctor1->getResultInterfaceType()); auto resType2 = ctor2->mapTypeIntoContext( ctor2->getResultInterfaceType()); if (!resType1->isEqual(resType2)) { if (TypeChecker::isSubtypeOf(resType1, resType2, cs.DC)) { score1 += weight; } else if (TypeChecker::isSubtypeOf(resType2, resType1, cs.DC)) { score2 += weight; } } } } } } // If both declarations come from Clang, and one is a type and the other // is a function, prefer the function. if (decl1->hasClangNode() && decl2->hasClangNode() && ((isa<TypeDecl>(decl1) && isa<AbstractFunctionDecl>(decl2)) || (isa<AbstractFunctionDecl>(decl1) && isa<TypeDecl>(decl2)))) { if (isa<TypeDecl>(decl1)) score2 += weight; else score1 += weight; } // A class member is always better than a curried instance member. // If the members agree on instance-ness, a property is better than a // method (because a method is usually immediately invoked). if (!decl1->isInstanceMember() && decl2->isInstanceMember()) score1 += weight; else if (!decl2->isInstanceMember() && decl1->isInstanceMember()) score2 += weight; else if (isa<VarDecl>(decl1) && isa<FuncDecl>(decl2)) score1 += weight; else if (isa<VarDecl>(decl2) && isa<FuncDecl>(decl1)) score2 += weight; // If both are class properties with the same name, prefer // the one attached to the subclass because it could only be // found if requested directly. if (!decl1->isInstanceMember() && !decl2->isInstanceMember()) { if (isa<VarDecl>(decl1) && isa<VarDecl>(decl2)) { auto *nominal1 = dc1->getSelfNominalTypeDecl(); auto *nominal2 = dc2->getSelfNominalTypeDecl(); if (nominal1 && nominal2 && nominal1 != nominal2) { auto base1 = nominal1->getDeclaredType(); auto base2 = nominal2->getDeclaredType(); if (isNominallySuperclassOf(base1, base2)) score2 += weight; if (isNominallySuperclassOf(base2, base1)) score1 += weight; } } } // If we haven't found a refinement, record whether one overload is in // any way more constrained than another. We'll only utilize this // information in the case of a potential ambiguity. if (!(foundRefinement1 && foundRefinement2)) { if (isDeclMoreConstrainedThan(decl1, decl2)) { foundRefinement1 = true; } if (isDeclMoreConstrainedThan(decl2, decl1)) { foundRefinement2 = true; } } // FIXME: The rest of the hack for restating requirements. if (!(foundRefinement1 && foundRefinement2)) { if (identical && decl1InSubprotocol != decl2InSubprotocol) { foundRefinement1 = decl1InSubprotocol; foundRefinement2 = decl2InSubprotocol; } } // Swift 4.1 compatibility hack: If everything else is considered equal, // favour a property on a concrete type over a protocol property member. // // This hack is required due to changes in shadowing behaviour where a // protocol property member will no longer shadow a property on a concrete // type, which created unintentional ambiguities in 4.2. This hack ensures // we at least keep these cases unambiguous in Swift 5 under Swift 4 // compatibility mode. Don't however apply this hack for decls found through // dynamic lookup, as we want the user to have to disambiguate those. // // This is intentionally narrow in order to best preserve source // compatibility under Swift 4 mode by ensuring we don't introduce any new // ambiguities. This will become a more general "is more specialised" rule // in Swift 5 mode. if (!cs.getASTContext().isSwiftVersionAtLeast(5) && choice1.getKind() != OverloadChoiceKind::DeclViaDynamic && choice2.getKind() != OverloadChoiceKind::DeclViaDynamic && isa<VarDecl>(decl1) && isa<VarDecl>(decl2)) { auto *nominal1 = dc1->getSelfNominalTypeDecl(); auto *nominal2 = dc2->getSelfNominalTypeDecl(); if (nominal1 && nominal2 && nominal1 != nominal2) { isVarAndNotProtocol1 = !isa<ProtocolDecl>(nominal1); isVarAndNotProtocol2 = !isa<ProtocolDecl>(nominal2); } } // FIXME: Lousy hack for ?? to prefer the catamorphism (flattening) // over the mplus (non-flattening) overload if all else is equal. if (decl1->getBaseName() == "??") { assert(decl2->getBaseName() == "??"); auto check = [](const ValueDecl *VD) -> bool { if (!VD->getModuleContext()->isStdlibModule()) return false; auto fnTy = VD->getInterfaceType()->castTo<AnyFunctionType>(); if (!fnTy->getResult()->getOptionalObjectType()) return false; // Check that the standard library hasn't added another overload of // the ?? operator. auto params = fnTy->getParams(); assert(params.size() == 2); auto param1 = params[0].getParameterType(); auto param2 = params[1].getParameterType()->castTo<AnyFunctionType>(); assert(param1->getOptionalObjectType()); assert(params[1].isAutoClosure()); assert(param2->getResult()->getOptionalObjectType()); (void) param1; (void) param2; return true; }; isStdlibOptionalMPlusOperator1 = check(decl1); isStdlibOptionalMPlusOperator2 = check(decl2); } } // Compare the type variable bindings. llvm::DenseMap<TypeVariableType *, TypeBindingsToCompare> typeDiff; const auto &bindings1 = solutions[idx1].typeBindings; const auto &bindings2 = solutions[idx2].typeBindings; for (const auto &binding1 : bindings1) { auto *typeVar = binding1.first; auto *loc = typeVar->getImpl().getLocator();