@@ -3927,6 +3927,62 @@ static void diagnoseUnintendedOptionalBehavior(TypeChecker &TC, const Expr *E,
3927
3927
const_cast <Expr *>(E)->walk (Walker);
3928
3928
}
3929
3929
3930
+ static void diagnoseDeprecatedWritableKeyPath (TypeChecker &TC, const Expr *E,
3931
+ const DeclContext *DC) {
3932
+ if (!E || isa<ErrorExpr>(E) || !E->getType ())
3933
+ return ;
3934
+
3935
+ class DeprecatedWritableKeyPathWalker : public ASTWalker {
3936
+ TypeChecker &TC;
3937
+ const DeclContext *DC;
3938
+
3939
+ void visitKeyPathApplicationExpr (KeyPathApplicationExpr *E) {
3940
+ if (E->hasLValueAccessKind () &&
3941
+ E->getLValueAccessKind () == AccessKind::Read)
3942
+ return ;
3943
+
3944
+ if (auto *keyPathExpr = dyn_cast<KeyPathExpr>(E->getKeyPath ())) {
3945
+ auto *decl = keyPathExpr->getType ()->getNominalOrBoundGenericNominal ();
3946
+ if (decl != TC.Context .getWritableKeyPathDecl () &&
3947
+ decl != TC.Context .getReferenceWritableKeyPathDecl ())
3948
+ return ;
3949
+
3950
+ assert (keyPathExpr->getComponents ().size () > 0 );
3951
+ auto &component = keyPathExpr->getComponents ().back ();
3952
+ if (component.getKind () == KeyPathExpr::Component::Kind::Property) {
3953
+ auto *storage =
3954
+ cast<AbstractStorageDecl>(component.getDeclRef ().getDecl ());
3955
+ if (!storage->isSettable (nullptr ) ||
3956
+ !storage->isSetterAccessibleFrom (DC)) {
3957
+ TC.diagnose (keyPathExpr->getLoc (),
3958
+ swift::diag::expr_deprecated_writable_keypath,
3959
+ storage->getFullName ());
3960
+ }
3961
+ }
3962
+ }
3963
+ }
3964
+
3965
+ std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
3966
+ if (!E || isa<ErrorExpr>(E) || !E->getType ())
3967
+ return {false , E};
3968
+
3969
+ if (auto *KPAE = dyn_cast<KeyPathApplicationExpr>(E)) {
3970
+ visitKeyPathApplicationExpr (KPAE);
3971
+ return {true , E};
3972
+ }
3973
+
3974
+ return {true , E};
3975
+ }
3976
+
3977
+ public:
3978
+ DeprecatedWritableKeyPathWalker (TypeChecker &TC, const DeclContext *DC)
3979
+ : TC(TC), DC(DC) {}
3980
+ };
3981
+
3982
+ DeprecatedWritableKeyPathWalker Walker (TC, DC);
3983
+ const_cast <Expr *>(E)->walk (Walker);
3984
+ }
3985
+
3930
3986
// ===----------------------------------------------------------------------===//
3931
3987
// High-level entry points.
3932
3988
// ===----------------------------------------------------------------------===//
@@ -3940,6 +3996,8 @@ void swift::performSyntacticExprDiagnostics(TypeChecker &TC, const Expr *E,
3940
3996
diagRecursivePropertyAccess (TC, E, DC);
3941
3997
diagnoseImplicitSelfUseInClosure (TC, E, DC);
3942
3998
diagnoseUnintendedOptionalBehavior (TC, E, DC);
3999
+ if (!TC.Context .isSwiftVersionAtLeast (5 ))
4000
+ diagnoseDeprecatedWritableKeyPath (TC, E, DC);
3943
4001
if (!TC.getLangOpts ().DisableAvailabilityChecking )
3944
4002
diagAvailability (TC, E, const_cast <DeclContext*>(DC));
3945
4003
if (TC.Context .LangOpts .EnableObjCInterop )
0 commit comments