@@ -2072,10 +2072,10 @@ void AttributeChecker::visitDiscardableResultAttr(DiscardableResultAttr *attr) {
2072
2072
}
2073
2073
2074
2074
// / Lookup the replaced decl in the replacments scope.
2075
- void lookupReplacedDecl (DeclName replacedDeclName,
2076
- const DynamicReplacementAttr *attr,
2077
- const ValueDecl *replacement,
2078
- SmallVectorImpl<ValueDecl *> &results) {
2075
+ static void lookupReplacedDecl (DeclName replacedDeclName,
2076
+ const DynamicReplacementAttr *attr,
2077
+ const ValueDecl *replacement,
2078
+ SmallVectorImpl<ValueDecl *> &results) {
2079
2079
auto *declCtxt = replacement->getDeclContext ();
2080
2080
2081
2081
// Look at the accessors' storage's context.
@@ -2232,11 +2232,12 @@ findReplacedFunction(DeclName replacedFunctionName,
2232
2232
// Check for static/instance mismatch.
2233
2233
if (result->isStatic () != replacement->isStatic ())
2234
2234
continue ;
2235
-
2235
+
2236
+ auto resultTy = result->getInterfaceType ();
2237
+ auto replaceTy = replacement->getInterfaceType ();
2236
2238
TypeMatchOptions matchMode = TypeMatchFlags::AllowABICompatible;
2237
2239
matchMode |= TypeMatchFlags::AllowCompatibleOpaqueTypeArchetypes;
2238
- if (result->getInterfaceType ()->getCanonicalType ()->matches (
2239
- replacement->getInterfaceType ()->getCanonicalType (), matchMode)) {
2240
+ if (resultTy->matches (replaceTy, matchMode)) {
2240
2241
if (!result->isDynamic ()) {
2241
2242
if (Diags) {
2242
2243
Diags->diagnose (attr->getLocation (),
@@ -2286,9 +2287,11 @@ findReplacedStorageDecl(DeclName replacedFunctionName,
2286
2287
// Check for static/instance mismatch.
2287
2288
if (result->isStatic () != replacement->isStatic ())
2288
2289
continue ;
2289
- if (result->getInterfaceType ()->getCanonicalType ()->matches (
2290
- replacement->getInterfaceType ()->getCanonicalType (),
2291
- TypeMatchFlags::AllowABICompatible)) {
2290
+ auto resultTy = result->getInterfaceType ();
2291
+ auto replaceTy = replacement->getInterfaceType ();
2292
+ TypeMatchOptions matchMode = TypeMatchFlags::AllowABICompatible;
2293
+ matchMode |= TypeMatchFlags::AllowCompatibleOpaqueTypeArchetypes;
2294
+ if (resultTy->matches (replaceTy, matchMode)) {
2292
2295
if (!result->isDynamic ()) {
2293
2296
return nullptr ;
2294
2297
}
@@ -2298,113 +2301,48 @@ findReplacedStorageDecl(DeclName replacedFunctionName,
2298
2301
return nullptr ;
2299
2302
}
2300
2303
2301
- ValueDecl *TypeChecker::findReplacedDynamicFunction (const ValueDecl *vd) {
2302
- assert (isa<AbstractFunctionDecl>(vd) || isa<AbstractStorageDecl>(vd));
2303
- if (isa<AccessorDecl>(vd))
2304
- return nullptr ;
2305
-
2306
- auto *attr = vd->getAttrs ().getAttribute <DynamicReplacementAttr>();
2307
- if (!attr)
2308
- return nullptr ;
2309
-
2310
- auto *afd = dyn_cast<AbstractFunctionDecl>(vd);
2311
- if (afd) {
2312
- // When we pass nullptr as the type checker argument attr is truely const.
2313
- return findReplacedFunction (attr->getReplacedFunctionName (), afd,
2314
- const_cast <DynamicReplacementAttr *>(attr),
2315
- nullptr );
2316
- }
2317
- auto *storageDecl = dyn_cast<AbstractStorageDecl>(vd);
2318
- if (!storageDecl)
2319
- return nullptr ;
2320
- return findReplacedStorageDecl (attr->getReplacedFunctionName (), storageDecl, attr);
2321
- }
2322
-
2323
2304
void AttributeChecker::visitDynamicReplacementAttr (DynamicReplacementAttr *attr) {
2324
2305
assert (isa<AbstractFunctionDecl>(D) || isa<AbstractStorageDecl>(D));
2325
- auto *VD = cast<ValueDecl>(D);
2306
+ auto *replacement = cast<ValueDecl>(D);
2326
2307
2327
- if (!isa<ExtensionDecl>(VD ->getDeclContext ()) &&
2328
- !VD ->getDeclContext ()->isModuleScopeContext ()) {
2308
+ if (!isa<ExtensionDecl>(replacement ->getDeclContext ()) &&
2309
+ !replacement ->getDeclContext ()->isModuleScopeContext ()) {
2329
2310
diagnose (attr->getLocation (), diag::dynamic_replacement_not_in_extension,
2330
- VD ->getBaseName ());
2311
+ replacement ->getBaseName ());
2331
2312
attr->setInvalid ();
2332
2313
return ;
2333
2314
}
2334
2315
2335
- if (VD ->isNativeDynamic ()) {
2316
+ if (replacement ->isNativeDynamic ()) {
2336
2317
diagnose (attr->getLocation (), diag::dynamic_replacement_must_not_be_dynamic,
2337
- VD ->getBaseName ());
2318
+ replacement ->getBaseName ());
2338
2319
attr->setInvalid ();
2339
2320
return ;
2340
2321
}
2341
2322
2342
- // Don't process a declaration twice. This will happen to accessor decls after
2343
- // we have processed their var decls.
2344
- if ( attr->getReplacedFunction ())
2323
+ auto *original = replacement-> getDynamicallyReplacedDecl ();
2324
+ if (!original) {
2325
+ attr->setInvalid ();
2345
2326
return ;
2346
-
2347
- SmallVector<AbstractFunctionDecl *, 4 > replacements;
2348
- SmallVector<AbstractFunctionDecl *, 4 > origs;
2349
-
2350
- // Collect the accessor replacement mapping if this is an abstract storage.
2351
- if (auto *var = dyn_cast<AbstractStorageDecl>(VD)) {
2352
- var->visitParsedAccessors ([&](AccessorDecl *accessor) {
2353
- if (attr->isInvalid ())
2354
- return ;
2355
-
2356
- auto *orig = findReplacedAccessor (attr->getReplacedFunctionName (),
2357
- accessor, attr, Ctx);
2358
- if (!orig)
2359
- return ;
2360
-
2361
- origs.push_back (orig);
2362
- replacements.push_back (accessor);
2363
- });
2364
- } else {
2365
- // Otherwise, find the matching function.
2366
- auto *fun = cast<AbstractFunctionDecl>(VD);
2367
- if (auto *orig = findReplacedFunction (attr->getReplacedFunctionName (), fun,
2368
- attr, &Ctx.Diags )) {
2369
- origs.push_back (orig);
2370
- replacements.push_back (fun);
2371
- } else
2372
- return ;
2373
2327
}
2374
2328
2375
- // Annotate the replacement with the original func decl.
2376
- for (auto index : indices (replacements)) {
2377
- if (auto *attr = replacements[index]
2378
- ->getAttrs ()
2379
- .getAttribute <DynamicReplacementAttr>()) {
2380
- auto *replacedFun = origs[index];
2381
- auto *replacement = replacements[index];
2382
- if (replacedFun->isObjC () && !replacement->isObjC ()) {
2383
- diagnose (attr->getLocation (),
2384
- diag::dynamic_replacement_replacement_not_objc_dynamic,
2385
- attr->getReplacedFunctionName ());
2386
- attr->setInvalid ();
2387
- return ;
2388
- }
2389
- if (!replacedFun->isObjC () && replacement->isObjC ()) {
2390
- diagnose (attr->getLocation (),
2391
- diag::dynamic_replacement_replaced_not_objc_dynamic,
2392
- attr->getReplacedFunctionName ());
2393
- attr->setInvalid ();
2394
- return ;
2395
- }
2396
- attr->setReplacedFunction (replacedFun);
2397
- continue ;
2398
- }
2399
- auto *newAttr = DynamicReplacementAttr::create (
2400
- VD->getASTContext (), attr->getReplacedFunctionName (), origs[index]);
2401
- DeclAttributes &attrs = replacements[index]->getAttrs ();
2402
- attrs.add (newAttr);
2329
+ if (original->isObjC () && !replacement->isObjC ()) {
2330
+ diagnose (attr->getLocation (),
2331
+ diag::dynamic_replacement_replacement_not_objc_dynamic,
2332
+ attr->getReplacedFunctionName ());
2333
+ attr->setInvalid ();
2334
+ }
2335
+ if (!original->isObjC () && replacement->isObjC ()) {
2336
+ diagnose (attr->getLocation (),
2337
+ diag::dynamic_replacement_replaced_not_objc_dynamic,
2338
+ attr->getReplacedFunctionName ());
2339
+ attr->setInvalid ();
2403
2340
}
2404
- if (auto *CD = dyn_cast<ConstructorDecl>(VD)) {
2341
+
2342
+ if (auto *CD = dyn_cast<ConstructorDecl>(replacement)) {
2405
2343
auto *attr = CD->getAttrs ().getAttribute <DynamicReplacementAttr>();
2406
2344
auto replacedIsConvenienceInit =
2407
- cast<ConstructorDecl>(attr-> getReplacedFunction () )->isConvenienceInit ();
2345
+ cast<ConstructorDecl>(original )->isConvenienceInit ();
2408
2346
if (replacedIsConvenienceInit &&!CD->isConvenienceInit ()) {
2409
2347
diagnose (attr->getLocation (),
2410
2348
diag::dynamic_replacement_replaced_constructor_is_convenience,
@@ -2416,13 +2354,6 @@ void AttributeChecker::visitDynamicReplacementAttr(DynamicReplacementAttr *attr)
2416
2354
attr->getReplacedFunctionName ());
2417
2355
}
2418
2356
}
2419
-
2420
-
2421
- // Remove the attribute on the abstract storage (we have moved it to the
2422
- // accessor decl).
2423
- if (!isa<AbstractStorageDecl>(VD))
2424
- return ;
2425
- D->getAttrs ().removeAttribute (attr);
2426
2357
}
2427
2358
2428
2359
void AttributeChecker::visitImplementsAttr (ImplementsAttr *attr) {
@@ -2911,3 +2842,53 @@ void TypeChecker::addImplicitDynamicAttribute(Decl *D) {
2911
2842
D->getAttrs ().add (attr);
2912
2843
}
2913
2844
}
2845
+
2846
+ llvm::Expected<ValueDecl *>
2847
+ DynamicallyReplacedDeclRequest::evaluate (Evaluator &evaluator,
2848
+ ValueDecl *VD) const {
2849
+ // Dynamic replacements must be explicit.
2850
+ if (VD->isImplicit ())
2851
+ return nullptr ;
2852
+
2853
+ auto *attr = VD->getAttrs ().getAttribute <DynamicReplacementAttr>();
2854
+ if (!attr) {
2855
+ // It's likely that the accessor isn't annotated but its storage is.
2856
+ if (auto *AD = dyn_cast<AccessorDecl>(VD)) {
2857
+ // Try to grab the attribute from the storage.
2858
+ attr = AD->getStorage ()->getAttrs ().getAttribute <DynamicReplacementAttr>();
2859
+ }
2860
+
2861
+ if (!attr) {
2862
+ // Otherwise, it's not dynamically replacing anything.
2863
+ return nullptr ;
2864
+ }
2865
+ }
2866
+
2867
+ // If the attribute is invalid, bail.
2868
+ if (attr->isInvalid ())
2869
+ return nullptr ;
2870
+
2871
+ // If we can lazily resolve the function, do so now.
2872
+ if (auto *LazyResolver = attr->Resolver ) {
2873
+ auto decl = attr->Resolver ->loadDynamicallyReplacedFunctionDecl (
2874
+ attr, attr->ResolverContextData );
2875
+ attr->Resolver = nullptr ;
2876
+ return decl;
2877
+ }
2878
+
2879
+ auto &Ctx = VD->getASTContext ();
2880
+ if (auto *AD = dyn_cast<AccessorDecl>(VD)) {
2881
+ return findReplacedAccessor (attr->getReplacedFunctionName (), AD, attr, Ctx);
2882
+ }
2883
+
2884
+ if (auto *AFD = dyn_cast<AbstractFunctionDecl>(VD)) {
2885
+ return findReplacedFunction (attr->getReplacedFunctionName (), AFD,
2886
+ attr, &Ctx.Diags );
2887
+ }
2888
+
2889
+ if (auto *SD = dyn_cast<AbstractStorageDecl>(VD)) {
2890
+ return findReplacedStorageDecl (attr->getReplacedFunctionName (), SD, attr);
2891
+ }
2892
+
2893
+ return nullptr ;
2894
+ }
0 commit comments