Skip to content

Commit f12afd2

Browse files
authored
Merge pull request #8010 from KingOfBrian/bugfix/SR-1762-Remove-Final-In-Protocol-Extensions
Remove final in protocol extensions
2 parents d99d399 + 0770037 commit f12afd2

22 files changed

+160
-149
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,6 +1988,9 @@ ERROR(override_static,none,
19881988
ERROR(member_cannot_be_final,none,
19891989
"only classes and class members may be marked with 'final'",
19901990
())
1991+
WARNING(protocol_extension_cannot_be_final,none,
1992+
"functions in a protocol extension do not need to be marked with 'final'",
1993+
())
19911994

19921995
ERROR(final_not_allowed_here,none,
19931996
"'final' may only be applied to classes, properties, methods, and "

lib/Sema/TypeCheckAttr.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -183,15 +183,20 @@ class AttributeEarlyChecker : public AttributeVisitor<AttributeEarlyChecker> {
183183
if (isa<ClassDecl>(D))
184184
return;
185185

186-
// 'final' only makes sense in the context of a class
187-
// declaration or a protocol extension. Reject it on global functions,
188-
// structs, enums, etc.
189-
if (D->getDeclContext()->getAsProtocolExtensionContext()) {
190-
// Accept and remove the 'final' attribute from members of protocol
191-
// extensions.
186+
// 'final' only makes sense in the context of a class declaration.
187+
// Reject it on global functions, protocols, structs, enums, etc.
188+
if (!D->getDeclContext()->getAsClassOrClassExtensionContext()) {
189+
if (D->getDeclContext()->getAsProtocolExtensionContext())
190+
TC.diagnose(attr->getLocation(),
191+
diag::protocol_extension_cannot_be_final)
192+
.fixItRemove(attr->getRange());
193+
else
194+
TC.diagnose(attr->getLocation(), diag::member_cannot_be_final)
195+
.fixItRemove(attr->getRange());
196+
197+
// Remove the attribute so child declarations are not flagged as final
198+
// and duplicate the error message.
192199
D->getAttrs().removeAttribute(attr);
193-
} else if (!D->getDeclContext()->getAsClassOrClassExtensionContext()) {
194-
diagnoseAndRemoveAttr(attr, diag::member_cannot_be_final);
195200
return;
196201
}
197202
}
@@ -1009,7 +1014,8 @@ void AttributeChecker::visitFinalAttr(FinalAttr *attr) {
10091014
// We currently only support final on var/let, func and subscript
10101015
// declarations.
10111016
if (!isa<VarDecl>(D) && !isa<FuncDecl>(D) && !isa<SubscriptDecl>(D)) {
1012-
TC.diagnose(attr->getLocation(), diag::final_not_allowed_here);
1017+
TC.diagnose(attr->getLocation(), diag::final_not_allowed_here)
1018+
.fixItRemove(attr->getRange());
10131019
return;
10141020
}
10151021

@@ -1018,7 +1024,8 @@ void AttributeChecker::visitFinalAttr(FinalAttr *attr) {
10181024
unsigned Kind = 2;
10191025
if (auto *VD = dyn_cast<VarDecl>(FD->getAccessorStorageDecl()))
10201026
Kind = VD->isLet() ? 1 : 0;
1021-
TC.diagnose(attr->getLocation(), diag::final_not_on_accessors, Kind);
1027+
TC.diagnose(attr->getLocation(), diag::final_not_on_accessors, Kind)
1028+
.fixItRemove(attr->getRange());
10221029
return;
10231030
}
10241031
}

stdlib/public/SDK/Foundation/NSError.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,8 @@ extension __BridgedNSError
380380

381381
public extension __BridgedNSError
382382
where Self: RawRepresentable, Self.RawValue: SignedInteger {
383-
public final var _domain: String { return Self._nsErrorDomain }
384-
public final var _code: Int { return Int(rawValue.toIntMax()) }
383+
public var _domain: String { return Self._nsErrorDomain }
384+
public var _code: Int { return Int(rawValue.toIntMax()) }
385385

386386
public init?(rawValue: RawValue) {
387387
self = unsafeBitCast(rawValue, to: Self.self)
@@ -395,7 +395,7 @@ public extension __BridgedNSError
395395
self.init(rawValue: RawValue(IntMax(_bridgedNSError.code)))
396396
}
397397

398-
public final var hashValue: Int { return _code }
398+
public var hashValue: Int { return _code }
399399
}
400400

401401
// Allow two bridged NSError types to be compared.
@@ -408,8 +408,8 @@ extension __BridgedNSError
408408

409409
public extension __BridgedNSError
410410
where Self: RawRepresentable, Self.RawValue: UnsignedInteger {
411-
public final var _domain: String { return Self._nsErrorDomain }
412-
public final var _code: Int {
411+
public var _domain: String { return Self._nsErrorDomain }
412+
public var _code: Int {
413413
return Int(bitPattern: UInt(rawValue.toUIntMax()))
414414
}
415415

@@ -425,7 +425,7 @@ public extension __BridgedNSError
425425
self.init(rawValue: RawValue(UIntMax(UInt(_bridgedNSError.code))))
426426
}
427427

428-
public final var hashValue: Int { return _code }
428+
public var hashValue: Int { return _code }
429429
}
430430

431431
/// Describes a raw representable type that is bridged to a particular

test/Generics/existential_restrictions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ protocol Mine {}
7373
class M1: Mine {}
7474
class M2: Mine {}
7575
extension Collection where Iterator.Element : Mine {
76-
final func takeAll() {}
76+
func takeAll() {}
7777
}
7878

7979
func foo() {

test/IRGen/protocol_extensions.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ public protocol P1 {
99
}
1010

1111
extension P1 {
12-
final func extP1a()
13-
public final func extP1b()
12+
func extP1a()
13+
public func extP1b()
1414
}
1515

1616
// CHECK-LABEL: define hidden swiftcc void @_TFP19protocol_extensions2P16extP1aUS0___fQPS0_FT_T_

test/IRGen/protocol_extensions_constrain.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public struct C2 : P2 {
2727
}
2828

2929
extension P2 where Self.Index : P3 {
30-
final public var bar: Bool {
30+
public var bar: Bool {
3131
let i = startIndex
3232
return i.foo(i)
3333
}

test/Interpreter/protocol_extensions.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
// Extend a protocol with a property.
55
extension Sequence {
6-
final var myCount: Int {
6+
var myCount: Int {
77
var result = 0
88
for _ in self {
99
result += 1
@@ -17,7 +17,7 @@ print(["a", "b", "c", "d"].myCount)
1717

1818
// Extend a protocol with a function.
1919
extension Collection {
20-
final var myIndices: Range<Index> {
20+
var myIndices: Range<Index> {
2121
return startIndex..<endIndex
2222
}
2323

@@ -30,7 +30,7 @@ extension Collection {
3030
print(["a", "b", "c", "d"].clone().myCount)
3131

3232
extension Sequence {
33-
final public func myEnumerated() -> EnumeratedSequence<Self> {
33+
public func myEnumerated() -> EnumeratedSequence<Self> {
3434
return self.enumerated()
3535
}
3636
}
@@ -43,7 +43,7 @@ for (index, element) in ["a", "b", "c"].myEnumerated() {
4343
}
4444

4545
extension Sequence {
46-
final public func myReduce<T>(
46+
public func myReduce<T>(
4747
_ initial: T, combine: (T, Self.Iterator.Element) -> T
4848
) -> T {
4949
var result = initial
@@ -59,7 +59,7 @@ print([1, 2, 3, 4, 5].myReduce(0, combine: +))
5959

6060

6161
extension Sequence {
62-
final public func myZip<S : Sequence>(_ s: S) -> Zip2Sequence<Self, S> {
62+
public func myZip<S : Sequence>(_ s: S) -> Zip2Sequence<Self, S> {
6363
return Zip2Sequence(_sequence1: self, _sequence2: s)
6464
}
6565
}
@@ -75,14 +75,14 @@ for (a, b) in [1, 2, 3].myZip(["a", "b", "c"]) {
7575
extension MutableCollection
7676
where Self: RandomAccessCollection, Self.Iterator.Element : Comparable {
7777

78-
public final mutating func myPartition() -> Index {
78+
public mutating func myPartition() -> Index {
7979
let first = self.first
8080
return self.partition(by: { $0 >= first! })
8181
}
8282
}
8383

8484
extension RangeReplaceableCollection {
85-
public final func myJoin<S : Sequence where S.Iterator.Element == Self>(
85+
public func myJoin<S : Sequence where S.Iterator.Element == Self>(
8686
_ elements: S
8787
) -> Self {
8888
var result = Self()
@@ -107,7 +107,7 @@ print(
107107

108108
// Constrained extensions for specific types.
109109
extension Collection where Self.Iterator.Element == String {
110-
final var myCommaSeparatedList: String {
110+
var myCommaSeparatedList: String {
111111
if startIndex == endIndex { return "" }
112112

113113
var result = ""
@@ -133,7 +133,7 @@ protocol ExistP1 {
133133
}
134134

135135
extension ExistP1 {
136-
final func runExistP1() {
136+
func runExistP1() {
137137
print("runExistP1")
138138
self.existP1()
139139
}
@@ -167,7 +167,7 @@ protocol P {
167167
}
168168

169169
extension P {
170-
final var extValue: Bool {
170+
var extValue: Bool {
171171
get { return getValue() }
172172
set(newValue) { setValue(newValue) }
173173
}

test/NameBinding/reference-dependencies.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,12 @@ typealias MyArray = Array<Bool>
107107

108108
// CHECK-DAG: "ExpressibleByArrayLiteral"
109109
extension ExpressibleByArrayLiteral {
110-
final func useless() {}
110+
func useless() {}
111111
}
112112

113113
// CHECK-DAG: OtherFileElementType
114114
extension ExpressibleByArrayLiteral where Element == OtherFileElementType {
115-
final func useless2() {}
115+
func useless2() {}
116116
}
117117

118118
// CHECK-DAG: "IntegerLiteralType"

test/NameBinding/scope_map_lookup.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,14 @@ class Superclass {
7373
protocol PConstrained4 { }
7474

7575
extension PConstrained4 where Self : Superclass {
76-
final func testFoo() -> Foo {
76+
func testFoo() -> Foo {
7777
foo()
7878
self.foo()
7979

8080
return Foo(5)
8181
}
8282

83-
final static func testBar() {
83+
static func testBar() {
8484
bar()
8585
self.bar()
8686
}

test/SILGen/boxed_existentials.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func test_property_of_lvalue(_ x: Error) -> String {
9898
// CHECK: return [[RESULT]]
9999
// CHECK: } // end sil function '_T018boxed_existentials23test_property_of_lvalueSSs5Error_pF'
100100
extension Error {
101-
final func extensionMethod() { }
101+
func extensionMethod() { }
102102
}
103103

104104
// CHECK-LABEL: sil hidden @_T018boxed_existentials21test_extension_methodys5Error_pF

test/SILGen/guaranteed_self.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ public protocol SequenceDefaults {
445445
}
446446

447447
extension SequenceDefaults {
448-
public final func _constrainElement(_: FakeGenerator.Element) {}
448+
public func _constrainElement(_: FakeGenerator.Element) {}
449449
}
450450

451451
public protocol Sequence : SequenceDefaults {

test/SILGen/protocol_extensions.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ struct Box {
1212
extension P1 {
1313
// CHECK-LABEL: sil hidden @_T019protocol_extensions2P1PAAE6extP1a{{[_0-9a-zA-Z]*}}F : $@convention(method) <Self where Self : P1> (@in_guaranteed Self) -> () {
1414
// CHECK: bb0([[SELF:%[0-9]+]] : $*Self):
15-
final func extP1a() {
15+
func extP1a() {
1616
// CHECK: [[WITNESS:%[0-9]+]] = witness_method $Self, #P1.reqP1a!1 : {{.*}} : $@convention(witness_method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> ()
1717
// CHECK-NEXT: apply [[WITNESS]]<Self>([[SELF]]) : $@convention(witness_method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> ()
1818
reqP1a()
@@ -21,7 +21,7 @@ extension P1 {
2121

2222
// CHECK-LABEL: sil @_T019protocol_extensions2P1PAAE6extP1b{{[_0-9a-zA-Z]*}}F : $@convention(method) <Self where Self : P1> (@in_guaranteed Self) -> () {
2323
// CHECK: bb0([[SELF:%[0-9]+]] : $*Self):
24-
public final func extP1b() {
24+
public func extP1b() {
2525
// CHECK: [[FN:%[0-9]+]] = function_ref @_T019protocol_extensions2P1PAAE6extP1a{{[_0-9a-zA-Z]*}}F : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> ()
2626
// CHECK-NEXT: apply [[FN]]<Self>([[SELF]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> ()
2727
extP1a()
@@ -36,7 +36,7 @@ extension P1 {
3636
set {}
3737
}
3838

39-
final func callSubscript() -> Int {
39+
func callSubscript() -> Int {
4040
// But here we have to do a witness method call:
4141

4242
// CHECK-LABEL: sil hidden @_T019protocol_extensions2P1PAAE13callSubscript{{[_0-9a-zA-Z]*}}F
@@ -474,24 +474,24 @@ func testG<T>(_ m: GenericMetaHolder<T>, gg: G<T>.Type) {
474474
// Using protocol extension members with existentials
475475
// ----------------------------------------------------------------------------
476476
extension P1 {
477-
final func f1() { }
477+
func f1() { }
478478

479-
final subscript (i: Int64) -> Bool {
479+
subscript (i: Int64) -> Bool {
480480
get { return true }
481481
}
482482

483-
final var prop: Bool {
483+
var prop: Bool {
484484
get { return true }
485485
}
486486

487-
final func returnsSelf() -> Self { return self }
487+
func returnsSelf() -> Self { return self }
488488

489-
final var prop2: Bool {
489+
var prop2: Bool {
490490
get { return true }
491491
set { }
492492
}
493493

494-
final subscript (b: Bool) -> Bool {
494+
subscript (b: Bool) -> Bool {
495495
get { return b }
496496
set { }
497497
}
@@ -641,7 +641,7 @@ func test_open_existential_semantics_opaque(_ guaranteed: P1,
641641
protocol CP1: class {}
642642

643643
extension CP1 {
644-
final func f1() { }
644+
func f1() { }
645645
}
646646

647647
func plusOneCP1() -> CP1 {}

test/SILGen/witnesses_canonical.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ struct _S<T : _CDT> : CT {
1414
}
1515

1616
extension _CDT {
17-
final subscript(b: Int) -> _S<Self> {
17+
subscript(b: Int) -> _S<Self> {
1818
return _S(a: self, b: b)
1919
}
2020
}

test/SILOptimizer/devirt_extension.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
protocol DrawingElementDispatch {}
44

55
extension DrawingElementDispatch {
6-
final var boundingBox: Int32 {
6+
var boundingBox: Int32 {
77
return 0
88
}
99
}

test/Serialization/Inputs/def_class.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public protocol Resettable {
5252
}
5353

5454
public extension Resettable {
55-
final func doReset() { self.reset() }
55+
func doReset() { self.reset() }
5656
}
5757

5858
open class ResettableIntWrapper : Resettable {
@@ -80,7 +80,7 @@ public protocol PairLike {
8080
}
8181

8282
public extension PairLike where FirstType : Cacheable {
83-
final func cacheFirst() { }
83+
func cacheFirst() { }
8484
}
8585

8686
public protocol ClassProto : class {}

test/SourceKit/DocSupport/Inputs/cake.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class C1 : Prot {
1717
public func genfoo<T1 : Prot, T2 : C1>(x ix: T1, y iy: T2) where T1.Element == Int, T2.Element == T1.Element {}
1818

1919
public extension Prot where Self.Element == Int {
20-
final func extfoo() {}
20+
func extfoo() {}
2121
}
2222

2323
public enum MyEnum : Int {

0 commit comments

Comments
 (0)