@@ -1977,8 +1977,8 @@ void AttributeChecker::visitDiscardableResultAttr(DiscardableResultAttr *attr) {
19771977
19781978// / Lookup the replaced decl in the replacments scope.
19791979void lookupReplacedDecl (DeclName replacedDeclName,
1980- DynamicReplacementAttr *attr,
1981- AbstractFunctionDecl *replacement,
1980+ const DynamicReplacementAttr *attr,
1981+ const ValueDecl *replacement,
19821982 SmallVectorImpl<ValueDecl *> &results) {
19831983 auto *declCtxt = replacement->getDeclContext ();
19841984
@@ -1988,9 +1988,9 @@ void lookupReplacedDecl(DeclName replacedDeclName,
19881988 declCtxt = storage->getDeclContext ();
19891989 }
19901990
1991+ auto *moduleScopeCtxt = declCtxt->getModuleScopeContext ();
19911992 if (isa<FileUnit>(declCtxt)) {
1992- UnqualifiedLookup lookup (replacedDeclName,
1993- replacement->getModuleScopeContext (), nullptr ,
1993+ UnqualifiedLookup lookup (replacedDeclName, moduleScopeCtxt, nullptr ,
19941994 attr->getLocation ());
19951995 if (lookup.isSuccess ()) {
19961996 for (auto entry : lookup.Results ) {
@@ -2005,8 +2005,8 @@ void lookupReplacedDecl(DeclName replacedDeclName,
20052005 if (!typeCtx)
20062006 typeCtx = cast<ExtensionDecl>(declCtxt->getAsDecl ())->getExtendedNominal ();
20072007
2008- replacement-> getModuleScopeContext ()-> lookupQualified (
2009- {typeCtx}, replacedDeclName, NL_QualifiedDefault, results);
2008+ moduleScopeCtxt-> lookupQualified ({typeCtx}, replacedDeclName,
2009+ NL_QualifiedDefault, results);
20102010}
20112011
20122012// / Remove any argument labels from the interface type of the given value that
@@ -2124,51 +2124,107 @@ static FuncDecl *findReplacedAccessor(DeclName replacedVarName,
21242124
21252125static AbstractFunctionDecl *
21262126findReplacedFunction (DeclName replacedFunctionName,
2127- AbstractFunctionDecl *replacement,
2128- DynamicReplacementAttr *attr, TypeChecker & TC) {
2127+ const AbstractFunctionDecl *replacement,
2128+ DynamicReplacementAttr *attr, TypeChecker * TC) {
21292129
2130+ // Note: we might pass a constant attribute when typechecker is nullptr.
2131+ // Any modification to attr must be guarded by a null check on TC.
2132+ //
21302133 SmallVector<ValueDecl *, 4 > results;
21312134 lookupReplacedDecl (replacedFunctionName, attr, replacement, results);
21322135
21332136 for (auto *result : results) {
21342137 // Check for static/instance mismatch.
21352138 if (result->isStatic () != replacement->isStatic ())
21362139 continue ;
2137-
2138- TC. validateDecl (result);
2140+ if (TC)
2141+ TC-> validateDecl (result);
21392142 if (result->getInterfaceType ()->getCanonicalType ()->matches (
21402143 replacement->getInterfaceType ()->getCanonicalType (),
21412144 TypeMatchFlags::AllowABICompatible)) {
21422145 if (!result->isDynamic ()) {
2143- TC.diagnose (attr->getLocation (),
2144- diag::dynamic_replacement_function_not_dynamic,
2145- replacedFunctionName);
2146- attr->setInvalid ();
2146+ if (TC) {
2147+ TC->diagnose (attr->getLocation (),
2148+ diag::dynamic_replacement_function_not_dynamic,
2149+ replacedFunctionName);
2150+ attr->setInvalid ();
2151+ }
21472152 return nullptr ;
21482153 }
21492154 return cast<AbstractFunctionDecl>(result);
21502155 }
21512156 }
2152- if (results.empty ())
2153- TC.diagnose (attr->getLocation (),
2154- diag::dynamic_replacement_function_not_found,
2155- attr->getReplacedFunctionName ());
2156- else {
2157- TC.diagnose (attr->getLocation (),
2158- diag::dynamic_replacement_function_of_type_not_found,
2159- attr->getReplacedFunctionName (),
2160- replacement->getInterfaceType ()->getCanonicalType ());
2157+
2158+ if (!TC)
2159+ return nullptr ;
2160+
2161+ if (results.empty ()) {
2162+ TC->diagnose (attr->getLocation (),
2163+ diag::dynamic_replacement_function_not_found,
2164+ attr->getReplacedFunctionName ());
2165+ } else {
2166+ TC->diagnose (attr->getLocation (),
2167+ diag::dynamic_replacement_function_of_type_not_found,
2168+ attr->getReplacedFunctionName (),
2169+ replacement->getInterfaceType ()->getCanonicalType ());
21612170
21622171 for (auto *result : results) {
2163- TC.diagnose (SourceLoc (), diag::dynamic_replacement_found_function_of_type,
2164- attr->getReplacedFunctionName (),
2165- result->getInterfaceType ()->getCanonicalType ());
2172+ TC->diagnose (SourceLoc (),
2173+ diag::dynamic_replacement_found_function_of_type,
2174+ attr->getReplacedFunctionName (),
2175+ result->getInterfaceType ()->getCanonicalType ());
21662176 }
21672177 }
21682178 attr->setInvalid ();
21692179 return nullptr ;
21702180}
21712181
2182+ static AbstractStorageDecl *
2183+ findReplacedStorageDecl (DeclName replacedFunctionName,
2184+ const AbstractStorageDecl *replacement,
2185+ const DynamicReplacementAttr *attr) {
2186+
2187+ SmallVector<ValueDecl *, 4 > results;
2188+ lookupReplacedDecl (replacedFunctionName, attr, replacement, results);
2189+
2190+ for (auto *result : results) {
2191+ // Check for static/instance mismatch.
2192+ if (result->isStatic () != replacement->isStatic ())
2193+ continue ;
2194+ if (result->getInterfaceType ()->getCanonicalType ()->matches (
2195+ replacement->getInterfaceType ()->getCanonicalType (),
2196+ TypeMatchFlags::AllowABICompatible)) {
2197+ if (!result->isDynamic ()) {
2198+ return nullptr ;
2199+ }
2200+ return cast<AbstractStorageDecl>(result);
2201+ }
2202+ }
2203+ return nullptr ;
2204+ }
2205+
2206+ ValueDecl *TypeChecker::findReplacedDynamicFunction (const ValueDecl *vd) {
2207+ assert (isa<AbstractFunctionDecl>(vd) || isa<AbstractStorageDecl>(vd));
2208+ if (isa<AccessorDecl>(vd))
2209+ return nullptr ;
2210+
2211+ auto *attr = vd->getAttrs ().getAttribute <DynamicReplacementAttr>();
2212+ if (!attr)
2213+ return nullptr ;
2214+
2215+ auto *afd = dyn_cast<AbstractFunctionDecl>(vd);
2216+ if (afd) {
2217+ // When we pass nullptr as the type checker argument attr is truely const.
2218+ return findReplacedFunction (attr->getReplacedFunctionName (), afd,
2219+ const_cast <DynamicReplacementAttr *>(attr),
2220+ nullptr );
2221+ }
2222+ auto *storageDecl = dyn_cast<AbstractStorageDecl>(vd);
2223+ if (!storageDecl)
2224+ return nullptr ;
2225+ return findReplacedStorageDecl (attr->getReplacedFunctionName (), storageDecl, attr);
2226+ }
2227+
21722228void TypeChecker::checkDynamicReplacementAttribute (ValueDecl *D) {
21732229 assert (isa<AbstractFunctionDecl>(D) || isa<AbstractStorageDecl>(D));
21742230
@@ -2217,7 +2273,7 @@ void TypeChecker::checkDynamicReplacementAttribute(ValueDecl *D) {
22172273 // Otherwise, find the matching function.
22182274 auto *fun = cast<AbstractFunctionDecl>(D);
22192275 if (auto *orig = findReplacedFunction (attr->getReplacedFunctionName (), fun,
2220- attr, * this )) {
2276+ attr, this )) {
22212277 origs.push_back (orig);
22222278 replacements.push_back (fun);
22232279 } else
0 commit comments