@@ -2275,6 +2275,12 @@ static void inferDynamic(ASTContext &ctx, ValueDecl *D) {
22752275 if (VD->isLet () && !isNSManaged) return ;
22762276 }
22772277
2278+ // Accessors should not infer 'dynamic' on their own; they can get it from
2279+ // their storage decls.
2280+ if (auto FD = dyn_cast<FuncDecl>(D))
2281+ if (FD->isAccessor ())
2282+ return ;
2283+
22782284 // The presence of 'final' on a class prevents 'dynamic'.
22792285 auto classDecl = D->getDeclContext ()->getAsClassOrClassExtensionContext ();
22802286 if (!classDecl) return ;
@@ -3859,6 +3865,9 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
38593865 if (isObjC && !TC.isRepresentableInObjC (SD, *isObjC))
38603866 isObjC = None;
38613867 markAsObjC (TC, SD, isObjC);
3868+
3869+ // Infer 'dynamic' before touching accessors.
3870+ inferDynamic (TC.Context , SD);
38623871 }
38633872
38643873 if (SD->hasAccessorFunctions ())
@@ -3887,8 +3896,6 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
38873896 synthesizeSetterForMutableAddressedStorage (SD, TC);
38883897 }
38893898
3890- inferDynamic (TC.Context , SD);
3891-
38923899 TC.checkDeclAttributes (SD);
38933900 }
38943901
@@ -4819,21 +4826,18 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
48194826 // The only additional condition we need to check is if the var decl
48204827 // had an @objc or @iboutlet property.
48214828
4822- ValueDecl *prop = cast<ValueDecl>( FD->getAccessorStorageDecl () );
4829+ AbstractStorageDecl *storage = FD->getAccessorStorageDecl ();
48234830 // Validate the subscript or property because it might not be type
48244831 // checked yet.
4825- if (isa<SubscriptDecl>(prop))
4826- TC.validateDecl (prop);
4827- else if (isa<VarDecl>(prop))
4828- TC.validateDecl (prop);
4832+ TC.validateDecl (storage);
48294833
4830- if (prop ->getAttrs ().hasAttribute <NonObjCAttr>())
4834+ if (storage ->getAttrs ().hasAttribute <NonObjCAttr>())
48314835 isObjC = None;
4832- else if (!isObjC && prop ->isObjC ())
4836+ else if (!isObjC && storage ->isObjC ())
48334837 isObjC = ObjCReason::DoNotDiagnose;
48344838
4835- // If the property is dynamic, propagate to this accessor.
4836- if (isObjC && prop ->isDynamic () && !FD->isDynamic ())
4839+ // If the storage is dynamic, propagate to this accessor.
4840+ if (isObjC && storage ->isDynamic () && !FD->isDynamic ())
48374841 FD->getAttrs ().add (new (TC.Context ) DynamicAttr (/* implicit*/ true ));
48384842 }
48394843
@@ -7065,6 +7069,7 @@ void TypeChecker::validateDecl(ValueDecl *D) {
70657069
70667070 markAsObjC (*this , VD, isObjC);
70677071
7072+ // Infer 'dynamic' before touching accessors.
70687073 inferDynamic (Context, VD);
70697074
70707075 // If this variable is a class member, mark it final if the
0 commit comments