@@ -2000,6 +2000,33 @@ 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::AllowTopLevelOptionalMismatch;
2017+ options |= TypeMatchFlags::AllowNonOptionalForIUOParam;
2018+ options |= TypeMatchFlags::IgnoreNonEscapingForOptionalFunctionParam;
2019+ options |= TypeMatchFlags::IgnoreFunctionSendability;
2020+ options |= TypeMatchFlags::IgnoreSendability;
2021+ options |= TypeMatchFlags::IgnoreFunctionGlobalActorIsolation;
2022+ if (type1->matches (type2, options))
2023+ return TypeComparison::NearMatch;
2024+ }
2025+
2026+ return TypeComparison::NotEqual;
2027+ }
2028+ }
2029+
20032030// / Remove values from \p values that don't match the expected type or module.
20042031// /
20052032// / Any of \p expectedTy, \p expectedModule, or \p expectedGenericSig can be
@@ -2015,8 +2042,10 @@ static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
20152042 if (expectedTy)
20162043 canTy = expectedTy->getCanonicalType ();
20172044
2045+ llvm::TinyPtrVector<ValueDecl *> clangNearMatches;
2046+
20182047 auto newEnd = std::remove_if (values.begin (), values.end (),
2019- [=](ValueDecl *value) {
2048+ [=, &clangNearMatches ](ValueDecl *value) {
20202049 // Ignore anything that was parsed (vs. deserialized), because a serialized
20212050 // module cannot refer to it.
20222051 if (value->getDeclContext ()->getParentSourceFile ())
@@ -2026,7 +2055,14 @@ static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
20262055 return true ;
20272056
20282057 // If we're expecting a type, make sure this decl has the expected type.
2029- if (canTy && !value->getInterfaceType ()->isEqual (canTy))
2058+ TypeComparison typesMatch = TypeComparison::Equal;
2059+ if (canTy) {
2060+ typesMatch = compareTypes (canTy,
2061+ value->getInterfaceType ()->getCanonicalType (),
2062+ importedFromClang);
2063+ }
2064+
2065+ if (typesMatch == TypeComparison::NotEqual)
20302066 return true ;
20312067
20322068 if (value->isStatic () != isStatic)
@@ -2075,9 +2111,20 @@ static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
20752111 cast<ConstructorDecl>(value)->getInitKind () != *ctorInit)
20762112 return true ;
20772113 }
2114+
2115+ // Record near matches.
2116+ if (typesMatch == TypeComparison::NearMatch) {
2117+ clangNearMatches.push_back (value);
2118+ return true ;
2119+ }
2120+
2121+ ASSERT (typesMatch == TypeComparison::Equal);
20782122 return false ;
20792123 });
20802124 values.erase (newEnd, values.end ());
2125+
2126+ if (values.empty ())
2127+ values.append (clangNearMatches.begin (), clangNearMatches.end ());
20812128}
20822129
20832130// / Look for nested types in all files of \p extensionModule except from the \p thisFile.
0 commit comments