From e3373a9efd9c9f01757f1d9878ec9981722e669c Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Sun, 29 Nov 2020 21:37:39 -0300 Subject: [PATCH 1/4] [Sema] Adding deprecation warning for protocol inheritance class keyword syntax --- include/swift/AST/DiagnosticsSema.def | 3 +++ lib/Sema/TypeCheckDeclPrimary.cpp | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index a5f141448b864..ed7adf8b82c10 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -2611,6 +2611,9 @@ WARNING(duplicate_anyobject_class_inheritance,none, "redundant inheritance from 'AnyObject' and Swift 3 'class' keyword", ()) ERROR(inheritance_from_protocol_with_superclass,none, "inheritance from class-constrained protocol composition type %0", (Type)) +WARNING(anyobject_class_inheritance_deprecated,none, + "using 'class' keyword for protocol inheritance is deprecated; " + "use 'AnyObject' instead", ()) ERROR(multiple_inheritance,none, "multiple inheritance from classes %0 and %1", (Type, Type)) ERROR(inheritance_from_non_protocol_or_class,none, diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 7109cad8bf31c..7c0cb04092d2b 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -179,6 +179,20 @@ static void checkInheritanceClause( // GenericSignatureBuilder (for protocol inheritance) or the // ConformanceLookupTable (for protocol conformance). if (inheritedTy->isAnyObject()) { + // Warn inherited AnyObject written as 'class' as deprecated + // for Swift >= 5. + auto sourceRange = inherited.getSourceRange(); + bool isWrittenAsClass = + (isa(decl) || isa(decl)) && + Lexer::getTokenAtLocation(ctx.SourceMgr, sourceRange.Start) + .is(tok::kw_class); + if (ctx.LangOpts.isSwiftVersionAtLeast(5) && isWrittenAsClass) { + diags + .diagnose(sourceRange.Start, + diag::anyobject_class_inheritance_deprecated) + .fixItReplace(sourceRange, "AnyObject"); + } + if (inheritedAnyObject) { // If the first occurrence was written as 'class', downgrade the error // to a warning in such case for backward compatibility with From c29fbb55283212d67084ef1564a2ece3344299aa Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Sun, 29 Nov 2020 21:43:50 -0300 Subject: [PATCH 2/4] [test] Adjusting test files where class syntax is used for protocol inheritance --- test/Parse/try_swift5.swift | 2 +- test/decl/func/dynamic_self.swift | 2 +- test/stdlib/Builtins.swift | 2 +- test/stdlib/Error.swift | 2 +- test/stdlib/ErrorBridged.swift | 2 +- test/stdlib/Mirror.swift | 2 +- test/stdlib/Reflection.swift | 2 +- test/stdlib/Runtime.swift.gyb | 2 +- test/stdlib/WeakMirror.swift | 4 ++-- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/Parse/try_swift5.swift b/test/Parse/try_swift5.swift index ec057527ed988..7398e4ff77d50 100644 --- a/test/Parse/try_swift5.swift +++ b/test/Parse/try_swift5.swift @@ -263,7 +263,7 @@ let _: Int??? = try? producer.produceDoubleOptionalInt() // good let _: String = try? producer.produceDoubleOptionalInt() // expected-error {{cannot convert value of type 'Int??' to specified type 'String'}} // rdar://problem/46742002 -protocol Dummy : class {} +protocol Dummy : AnyObject {} class F { func wait() throws -> T { fatalError() } diff --git a/test/decl/func/dynamic_self.swift b/test/decl/func/dynamic_self.swift index 0203c5f1e0f97..91c8aef78fbf4 100644 --- a/test/decl/func/dynamic_self.swift +++ b/test/decl/func/dynamic_self.swift @@ -44,7 +44,7 @@ extension P0 { } } -protocol P1: class { +protocol P1: AnyObject { func f() -> Self // okay func g(_ ds: Self) // okay diff --git a/test/stdlib/Builtins.swift b/test/stdlib/Builtins.swift index b5496c680082f..1be6786a41b9e 100644 --- a/test/stdlib/Builtins.swift +++ b/test/stdlib/Builtins.swift @@ -165,7 +165,7 @@ tests.test("array value witnesses") { expectEqual(NoisyLifeCount, NoisyDeathCount) } -protocol Classy : class {} +protocol Classy : AnyObject {} class A : Classy {} class B : A {} class C : B {} diff --git a/test/stdlib/Error.swift b/test/stdlib/Error.swift index 69602edd2d8ad..132c30c5f3057 100644 --- a/test/stdlib/Error.swift +++ b/test/stdlib/Error.swift @@ -15,7 +15,7 @@ protocol OtherProtocol { var otherProperty: String { get } } -protocol OtherClassProtocol : class { +protocol OtherClassProtocol : AnyObject { var otherClassProperty: String { get } } diff --git a/test/stdlib/ErrorBridged.swift b/test/stdlib/ErrorBridged.swift index b996dad5d213f..3ca707719b2bf 100644 --- a/test/stdlib/ErrorBridged.swift +++ b/test/stdlib/ErrorBridged.swift @@ -22,7 +22,7 @@ protocol OtherProtocol { var otherProperty: String { get } } -protocol OtherClassProtocol : class { +protocol OtherClassProtocol : AnyObject { var otherClassProperty: String { get } } diff --git a/test/stdlib/Mirror.swift b/test/stdlib/Mirror.swift index 4755be399ad11..f2b6437076fa7 100644 --- a/test/stdlib/Mirror.swift +++ b/test/stdlib/Mirror.swift @@ -514,7 +514,7 @@ mirrors.test("struct/WrapNSArray") { // Check that Mirror correctly reflects weak/unowned refs to both // Swift and ObjC objects from Swift structs and classes. -protocol WeakUnownedTestsP1: class { +protocol WeakUnownedTestsP1: AnyObject { func f1() -> Int } diff --git a/test/stdlib/Reflection.swift b/test/stdlib/Reflection.swift index 24761d17fa70d..15a4f713767bf 100644 --- a/test/stdlib/Reflection.swift +++ b/test/stdlib/Reflection.swift @@ -118,7 +118,7 @@ print("Fooable double:") fooable = 2.5 dump(fooable) -protocol Barrable : class {} +protocol Barrable : AnyObject {} extension Best: Barrable {} // CHECK-LABEL: Barrable class: diff --git a/test/stdlib/Runtime.swift.gyb b/test/stdlib/Runtime.swift.gyb index 072515203b994..1dcdcb8fc39cf 100644 --- a/test/stdlib/Runtime.swift.gyb +++ b/test/stdlib/Runtime.swift.gyb @@ -534,7 +534,7 @@ Runtime.test("abstraction barrier on casting generic param bound to existential" class Malkovich: Malkovichable { var malkovich: String { return "malkovich" } } -protocol Malkovichable: class { +protocol Malkovichable: AnyObject { var malkovich: String { get } } diff --git a/test/stdlib/WeakMirror.swift b/test/stdlib/WeakMirror.swift index 02e88fdf33754..358d21ffe56b1 100644 --- a/test/stdlib/WeakMirror.swift +++ b/test/stdlib/WeakMirror.swift @@ -35,7 +35,7 @@ class NativeSwiftClass : NativeClassBoundExistential { } } -protocol NativeClassBoundExistential : class { +protocol NativeClassBoundExistential : AnyObject { var x: Int { get } } class NativeSwiftClassHasWeak { @@ -123,7 +123,7 @@ mirrors.test("class/NativeSwiftClassHasNativeWeakReferenceNoLeak") { import Foundation -@objc protocol ObjCClassExistential : class { +@objc protocol ObjCClassExistential : AnyObject { var weakProperty: AnyObject? { get set } var x: Int { get } } From 158bf613594a8f9700359985e26a30c67db2878f Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Sun, 29 Nov 2020 21:44:03 -0300 Subject: [PATCH 3/4] [test] Adding specific tests for the warning for protocol inheritance class keyword syntax deprecation --- test/decl/inherit/inherit_anyobject_protocol.swift | 7 +++++++ .../inherit/inherit_anyobject_protocol_swift5.swift | 10 ++++++++++ 2 files changed, 17 insertions(+) create mode 100644 test/decl/inherit/inherit_anyobject_protocol.swift create mode 100644 test/decl/inherit/inherit_anyobject_protocol_swift5.swift diff --git a/test/decl/inherit/inherit_anyobject_protocol.swift b/test/decl/inherit/inherit_anyobject_protocol.swift new file mode 100644 index 0000000000000..33675129c001b --- /dev/null +++ b/test/decl/inherit/inherit_anyobject_protocol.swift @@ -0,0 +1,7 @@ +// RUN: %target-typecheck-verify-swift + +protocol P: class {} +protocol P1: AnyObject {} +protocol P2 {} +protocol P3: class, P2 {} +protocol P4: P2, class {} // expected-error {{'class' must come first in the requirement list}} diff --git a/test/decl/inherit/inherit_anyobject_protocol_swift5.swift b/test/decl/inherit/inherit_anyobject_protocol_swift5.swift new file mode 100644 index 0000000000000..84ef9368880fc --- /dev/null +++ b/test/decl/inherit/inherit_anyobject_protocol_swift5.swift @@ -0,0 +1,10 @@ +// RUN: %target-typecheck-verify-swift -swift-version 5 + +protocol P: class {} +// expected-warning@-1 {{using 'class' keyword for protocol inheritance is deprecated; use 'AnyObject' instead}} {{13-18=AnyObject}} +protocol P1: AnyObject {} +protocol P2 {} +protocol P3: class, P2 {} +// expected-warning@-1 {{using 'class' keyword for protocol inheritance is deprecated; use 'AnyObject' instead}} {{14-19=AnyObject}} +protocol P4: P2, class {} // expected-error {{'class' must come first in the requirement list}} +// expected-warning@-1 {{using 'class' keyword for protocol inheritance is deprecated; use 'AnyObject' instead}} {{18-23=AnyObject}} From 338faab324b79ce03e96aacff726c054ba9afb16 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Sun, 29 Nov 2020 21:44:42 -0300 Subject: [PATCH 4/4] [test] Adjusting stdlib ocurrences where class syntax is used for protocol inheritance --- stdlib/public/Darwin/CoreFoundation/CoreFoundation.swift | 2 +- stdlib/public/core/BridgeObjectiveC.swift | 2 +- stdlib/public/core/ExistentialCollection.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stdlib/public/Darwin/CoreFoundation/CoreFoundation.swift b/stdlib/public/Darwin/CoreFoundation/CoreFoundation.swift index edf4ec460d24d..f9490218e15e3 100644 --- a/stdlib/public/Darwin/CoreFoundation/CoreFoundation.swift +++ b/stdlib/public/Darwin/CoreFoundation/CoreFoundation.swift @@ -12,7 +12,7 @@ @_exported import CoreFoundation -public protocol _CFObject: class, Hashable {} +public protocol _CFObject: AnyObject, Hashable {} extension _CFObject { public var hashValue: Int { return Int(bitPattern: CFHash(self)) diff --git a/stdlib/public/core/BridgeObjectiveC.swift b/stdlib/public/core/BridgeObjectiveC.swift index 07f4c6c1cdc32..1a10c0bae9b77 100644 --- a/stdlib/public/core/BridgeObjectiveC.swift +++ b/stdlib/public/core/BridgeObjectiveC.swift @@ -681,7 +681,7 @@ public func _conditionallyBridgeFromObjectiveC_bridgeable() -> T?