@@ -2608,6 +2608,15 @@ static bool isAsyncAlternativeOfOtherDecl(const ValueDecl *VD) {
26082608 return false ;
26092609}
26102610
2611+ static bool isStringNestedType (const ValueDecl *VD, StringRef Typename) {
2612+ auto ctx = VD->getDeclContext ();
2613+ return VD->hasName () && VD->getName ().isSimpleName () &&
2614+ VD->getBaseIdentifier ().str () == Typename &&
2615+ isa<ExtensionDecl>(ctx->getAsDecl ()) &&
2616+ cast<ExtensionDecl>(ctx->getAsDecl ())->getExtendedNominal () ==
2617+ VD->getASTContext ().getStringDecl ();
2618+ }
2619+
26112620static bool hasExposeAttr (const ValueDecl *VD, bool isExtension = false ) {
26122621 if (isa<NominalTypeDecl>(VD) && VD->getModuleContext ()->isStdlibModule ()) {
26132622 if (VD == VD->getASTContext ().getStringDecl () && !isExtension)
@@ -2616,6 +2625,8 @@ static bool hasExposeAttr(const ValueDecl *VD, bool isExtension = false) {
26162625 return true ;
26172626 if (VD == VD->getASTContext ().getOptionalDecl () && !isExtension)
26182627 return true ;
2628+ if (isStringNestedType (VD, " UTF8View" ) || isStringNestedType (VD, " Index" ))
2629+ return true ;
26192630 return false ;
26202631 }
26212632 // Clang decls don't need to be explicitly exposed.
@@ -2643,6 +2654,33 @@ static bool hasExposeAttr(const ValueDecl *VD, bool isExtension = false) {
26432654 .contains_insensitive (" index" ))
26442655 return false ;
26452656 }
2657+ if (ED->getExtendedNominal () == VD->getASTContext ().getStringDecl ()) {
2658+ if (isa<ValueDecl>(VD) &&
2659+ !cast<ValueDecl>(VD)->getName ().getBaseName ().isSpecial () &&
2660+ cast<ValueDecl>(VD)
2661+ ->getName ()
2662+ .getBaseName ()
2663+ .getIdentifier ()
2664+ .str ()
2665+ .contains_insensitive (" utf8" ))
2666+ return true ;
2667+ }
2668+ if (isStringNestedType (ED->getExtendedNominal (), " UTF8View" )) {
2669+ // Do not expose ambiguous 'index(after:' / 'index(before:' overloads.
2670+ if (isa<AbstractFunctionDecl>(VD) &&
2671+ cast<AbstractFunctionDecl>(VD)->getParameters ()->size () == 1 &&
2672+ !cast<AbstractFunctionDecl>(VD)
2673+ ->getName ()
2674+ .getBaseName ()
2675+ .isSpecial () &&
2676+ cast<AbstractFunctionDecl>(VD)
2677+ ->getName ()
2678+ .getBaseName ()
2679+ .getIdentifier ()
2680+ .str ()
2681+ .contains_insensitive (" index" ))
2682+ return false ;
2683+ }
26462684 return hasExposeAttr (ED->getExtendedNominal (), /* isExtension=*/ true );
26472685 }
26482686 return false ;
0 commit comments