@@ -2000,6 +2000,34 @@ static bool isReExportedToModule(const ValueDecl *value,
20002000 return exportedName == expectedModule->getName ().str ();
20012001}
20022002
2003+ namespace {
2004+ // / The result of a type comparison.
2005+ enum class TypeComparison {
2006+ NotEqual,
2007+ Equal,
2008+ NearMatch,
2009+ };
2010+
2011+ TypeComparison compareTypes (CanType type1, CanType type2, bool nearMatchOk) {
2012+ if (type1->isEqual (type2))
2013+ return TypeComparison::Equal;
2014+
2015+ if (nearMatchOk) {
2016+ TypeMatchOptions options = TypeMatchFlags::RequireMatchingParameterLabels;
2017+ options |= TypeMatchFlags::AllowTopLevelOptionalMismatch;
2018+ options |= TypeMatchFlags::AllowNonOptionalForIUOParam;
2019+ options |= TypeMatchFlags::IgnoreNonEscapingForOptionalFunctionParam;
2020+ options |= TypeMatchFlags::IgnoreFunctionSendability;
2021+ options |= TypeMatchFlags::IgnoreSendability;
2022+ options |= TypeMatchFlags::IgnoreFunctionGlobalActorIsolation;
2023+ if (type1->matches (type2, options))
2024+ return TypeComparison::NearMatch;
2025+ }
2026+
2027+ return TypeComparison::NotEqual;
2028+ }
2029+ }
2030+
20032031// / Remove values from \p values that don't match the expected type or module.
20042032// /
20052033// / Any of \p expectedTy, \p expectedModule, or \p expectedGenericSig can be
@@ -2015,8 +2043,10 @@ static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
20152043 if (expectedTy)
20162044 canTy = expectedTy->getCanonicalType ();
20172045
2046+ llvm::TinyPtrVector<ValueDecl *> clangNearMatches;
2047+
20182048 auto newEnd = std::remove_if (values.begin (), values.end (),
2019- [=](ValueDecl *value) {
2049+ [=, &clangNearMatches ](ValueDecl *value) {
20202050 // Ignore anything that was parsed (vs. deserialized), because a serialized
20212051 // module cannot refer to it.
20222052 if (value->getDeclContext ()->getParentSourceFile ())
@@ -2026,7 +2056,14 @@ static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
20262056 return true ;
20272057
20282058 // If we're expecting a type, make sure this decl has the expected type.
2029- if (canTy && !value->getInterfaceType ()->isEqual (canTy))
2059+ TypeComparison typesMatch = TypeComparison::Equal;
2060+ if (canTy) {
2061+ typesMatch = compareTypes (canTy,
2062+ value->getInterfaceType ()->getCanonicalType (),
2063+ importedFromClang);
2064+ }
2065+
2066+ if (typesMatch == TypeComparison::NotEqual)
20302067 return true ;
20312068
20322069 if (value->isStatic () != isStatic)
@@ -2075,9 +2112,20 @@ static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
20752112 cast<ConstructorDecl>(value)->getInitKind () != *ctorInit)
20762113 return true ;
20772114 }
2115+
2116+ // Record near matches.
2117+ if (typesMatch == TypeComparison::NearMatch) {
2118+ clangNearMatches.push_back (value);
2119+ return true ;
2120+ }
2121+
2122+ ASSERT (typesMatch == TypeComparison::Equal);
20782123 return false ;
20792124 });
20802125 values.erase (newEnd, values.end ());
2126+
2127+ if (values.empty ())
2128+ values.append (clangNearMatches.begin (), clangNearMatches.end ());
20812129}
20822130
20832131// / Look for nested types in all files of \p extensionModule except from the \p thisFile.
0 commit comments