@@ -1050,11 +1050,6 @@ static void validatePatternBindingEntries(TypeChecker &tc,
1050
1050
validatePatternBindingEntry (tc, binding, i);
1051
1051
}
1052
1052
1053
- void swift::makeFinal (ASTContext &ctx, ValueDecl *D) {
1054
- assert (isa<ClassDecl>(D) || D->isPotentiallyOverridable ());
1055
- D->getAttrs ().add (new (ctx) FinalAttr (/* IsImplicit=*/ true ));
1056
- }
1057
-
1058
1053
namespace {
1059
1054
// The raw values of this enum must be kept in sync with
1060
1055
// diag::implicitly_final_cannot_be_open.
@@ -1068,12 +1063,8 @@ enum class ImplicitlyFinalReason : unsigned {
1068
1063
};
1069
1064
}
1070
1065
1071
- static bool inferFinalAndDiagnoseIfNeeded (ValueDecl *D,
1066
+ static bool inferFinalAndDiagnoseIfNeeded (ValueDecl *D, ClassDecl *cls,
1072
1067
StaticSpellingKind staticSpelling) {
1073
- auto cls = D->getDeclContext ()->getSelfClassDecl ();
1074
- if (!cls)
1075
- return false ;
1076
-
1077
1068
// Are there any reasons to infer 'final'? Prefer 'static' over the class
1078
1069
// being final for the purposes of diagnostics.
1079
1070
Optional<ImplicitlyFinalReason> reason;
@@ -1184,15 +1175,28 @@ doesAccessorNeedDynamicAttribute(AccessorDecl *accessor, Evaluator &evaluator) {
1184
1175
1185
1176
llvm::Expected<bool >
1186
1177
IsFinalRequest::evaluate (Evaluator &evaluator, ValueDecl *decl) const {
1178
+ if (isa<ClassDecl>(decl))
1179
+ return decl->getAttrs ().hasAttribute <FinalAttr>();
1180
+
1181
+ auto cls = decl->getDeclContext ()->getSelfClassDecl ();
1182
+ if (!cls)
1183
+ return false ;
1184
+
1187
1185
switch (decl->getKind ()) {
1188
1186
case DeclKind::Var: {
1189
1187
// Properties are final if they are declared 'static' or a 'let'
1190
1188
auto *VD = cast<VarDecl>(decl);
1189
+
1190
+ // Backing storage for 'lazy' or property wrappers is always final.
1191
+ if (VD->isLazyStorageProperty () ||
1192
+ VD->getOriginalWrappedProperty ())
1193
+ return true ;
1194
+
1191
1195
if (auto *nominalDecl = VD->getDeclContext ()->getSelfClassDecl ()) {
1192
1196
// If this variable is a class member, mark it final if the
1193
1197
// class is final, or if it was declared with 'let'.
1194
1198
auto *PBD = VD->getParentPatternBinding ();
1195
- if (PBD && inferFinalAndDiagnoseIfNeeded (decl, PBD->getStaticSpelling ()))
1199
+ if (PBD && inferFinalAndDiagnoseIfNeeded (decl, cls, PBD->getStaticSpelling ()))
1196
1200
return true ;
1197
1201
1198
1202
if (VD->isLet ()) {
@@ -1217,7 +1221,7 @@ IsFinalRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
1217
1221
case DeclKind::Func: {
1218
1222
// Methods declared 'static' are final.
1219
1223
auto staticSpelling = cast<FuncDecl>(decl)->getStaticSpelling ();
1220
- if (inferFinalAndDiagnoseIfNeeded (decl, staticSpelling))
1224
+ if (inferFinalAndDiagnoseIfNeeded (decl, cls, staticSpelling))
1221
1225
return true ;
1222
1226
break ;
1223
1227
}
@@ -1228,9 +1232,7 @@ IsFinalRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
1228
1232
case AccessorKind::DidSet:
1229
1233
case AccessorKind::WillSet:
1230
1234
// Observing accessors are marked final if in a class.
1231
- if (accessor->getDeclContext ()->getSelfClassDecl ())
1232
- return true ;
1233
- break ;
1235
+ return true ;
1234
1236
1235
1237
case AccessorKind::Read:
1236
1238
case AccessorKind::Modify:
@@ -1252,7 +1254,7 @@ IsFinalRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
1252
1254
case DeclKind::Subscript: {
1253
1255
// Member subscripts.
1254
1256
auto staticSpelling = cast<SubscriptDecl>(decl)->getStaticSpelling ();
1255
- if (inferFinalAndDiagnoseIfNeeded (decl, staticSpelling))
1257
+ if (inferFinalAndDiagnoseIfNeeded (decl, cls, staticSpelling))
1256
1258
return true ;
1257
1259
break ;
1258
1260
}
0 commit comments