@@ -2036,8 +2036,9 @@ void lookupReplacedDecl(DeclName replacedDeclName,
20362036 replacement->getModuleScopeContext (), nullptr ,
20372037 attr->getLocation ());
20382038 if (lookup.isSuccess ()) {
2039- for (auto entry : lookup.Results )
2039+ for (auto entry : lookup.Results ) {
20402040 results.push_back (entry.getValueDecl ());
2041+ }
20412042 }
20422043 return ;
20432044 }
@@ -2051,6 +2052,28 @@ void lookupReplacedDecl(DeclName replacedDeclName,
20512052 {typeCtx}, replacedDeclName, NL_QualifiedDefault, results);
20522053}
20532054
2055+ // / Remove any argument labels from the interface type of the given value that
2056+ // / are extraneous from the type system's point of view, producing the
2057+ // / type to compare against for the purposes of dynamic replacement.
2058+ static Type getDynamicComparisonType (ValueDecl *value) {
2059+ unsigned numArgumentLabels = 0 ;
2060+
2061+ if (isa<AbstractFunctionDecl>(value)) {
2062+ ++numArgumentLabels;
2063+
2064+ if (value->getDeclContext ()->isTypeContext ())
2065+ ++numArgumentLabels;
2066+ } else if (isa<SubscriptDecl>(value)) {
2067+ ++numArgumentLabels;
2068+ }
2069+
2070+ auto interfaceType = value->getInterfaceType ();
2071+ if (interfaceType->hasError ())
2072+ return interfaceType;
2073+
2074+ return interfaceType->removeArgumentLabels (numArgumentLabels);
2075+ }
2076+
20542077static FuncDecl *findReplacedAccessor (DeclName replacedVarName,
20552078 AccessorDecl *replacement,
20562079 DynamicReplacementAttr *attr,
@@ -2060,13 +2083,47 @@ static FuncDecl *findReplacedAccessor(DeclName replacedVarName,
20602083 SmallVector<ValueDecl *, 4 > results;
20612084 lookupReplacedDecl (replacedVarName, attr, replacement, results);
20622085
2086+ // Filter out any accessors that won't work.
2087+ if (!results.empty ()) {
2088+ auto replacementStorage = replacement->getStorage ();
2089+ TC.validateDecl (replacementStorage);
2090+ Type replacementStorageType = getDynamicComparisonType (replacementStorage);
2091+ results.erase (std::remove_if (results.begin (), results.end (),
2092+ [&](ValueDecl *result) {
2093+ // Check for static/instance mismatch.
2094+ if (result->isStatic () != replacementStorage->isStatic ())
2095+ return true ;
2096+
2097+ // Check for type mismatch.
2098+ TC.validateDecl (result);
2099+ auto resultType = getDynamicComparisonType (result);
2100+ if (!resultType->isEqual (replacementStorageType)) {
2101+ return true ;
2102+ }
2103+
2104+ return false ;
2105+ }),
2106+ results.end ());
2107+ }
2108+
20632109 if (results.empty ()) {
20642110 TC.diagnose (attr->getLocation (),
20652111 diag::dynamic_replacement_accessor_not_found, replacedVarName);
20662112 attr->setInvalid ();
20672113 return nullptr ;
20682114 }
2069- assert (results.size () == 1 && " Should only have on var or fun" );
2115+
2116+ if (results.size () > 1 ) {
2117+ TC.diagnose (attr->getLocation (),
2118+ diag::dynamic_replacement_accessor_ambiguous, replacedVarName);
2119+ for (auto result : results) {
2120+ TC.diagnose (result,
2121+ diag::dynamic_replacement_accessor_ambiguous_candidate,
2122+ result->getModuleContext ()->getFullName ());
2123+ }
2124+ attr->setInvalid ();
2125+ return nullptr ;
2126+ }
20702127
20712128 assert (!isa<FuncDecl>(results[0 ]));
20722129 TC.validateDecl (results[0 ]);
@@ -2117,6 +2174,10 @@ findReplacedFunction(DeclName replacedFunctionName,
21172174 lookupReplacedDecl (replacedFunctionName, attr, replacement, results);
21182175
21192176 for (auto *result : results) {
2177+ // Check for static/instance mismatch.
2178+ if (result->isStatic () != replacement->isStatic ())
2179+ continue ;
2180+
21202181 TC.validateDecl (result);
21212182 if (result->getInterfaceType ()->getCanonicalType ()->matches (
21222183 replacement->getInterfaceType ()->getCanonicalType (),
0 commit comments