Skip to content

Commit 6e6de51

Browse files
authored
[Sema] Improve diagnostics for use of self access kind modifier on accessors inside classes (swiftlang#33602)
1 parent 24f1a46 commit 6e6de51

File tree

5 files changed

+29
-16
lines changed

5 files changed

+29
-16
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,8 +1294,9 @@ ERROR(nominal_type_not_attribute,none,
12941294

12951295
ERROR(mutating_invalid_global_scope,none, "%0 is only valid on methods",
12961296
(SelfAccessKind))
1297-
ERROR(mutating_invalid_classes,none, "%0 isn't valid on methods in "
1298-
"classes or class-bound protocols", (SelfAccessKind))
1297+
ERROR(mutating_invalid_classes,none, "%0 is not valid on %1s in "
1298+
"%select{classes|class-bound protocols}2",
1299+
(SelfAccessKind, DescriptiveDeclKind, bool))
12991300

13001301
ERROR(functions_mutating_and_not,none,
13011302
"method must not be declared both %0 and %1",

lib/Sema/TypeCheckAttr.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -317,14 +317,17 @@ void AttributeChecker::visitMutationAttr(DeclAttribute *attr) {
317317
llvm_unreachable("unhandled attribute kind");
318318
}
319319

320+
auto DC = FD->getDeclContext();
320321
// mutation attributes may only appear in type context.
321-
if (auto contextTy = FD->getDeclContext()->getDeclaredInterfaceType()) {
322+
if (auto contextTy = DC->getDeclaredInterfaceType()) {
322323
// 'mutating' and 'nonmutating' are not valid on types
323324
// with reference semantics.
324325
if (contextTy->hasReferenceSemantics()) {
325-
if (attrModifier != SelfAccessKind::Consuming)
326+
if (attrModifier != SelfAccessKind::Consuming) {
326327
diagnoseAndRemoveAttr(attr, diag::mutating_invalid_classes,
327-
attrModifier);
328+
attrModifier, FD->getDescriptiveKind(),
329+
DC->getSelfProtocolDecl() != nullptr);
330+
}
328331
}
329332
} else {
330333
diagnoseAndRemoveAttr(attr, diag::mutating_invalid_global_scope,

localization/diagnostics/en.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3350,7 +3350,7 @@
33503350
msg: "%0 is only valid on methods"
33513351

33523352
- id: mutating_invalid_classes
3353-
msg: "%0 isn't valid on methods in classes or class-bound protocols"
3353+
msg: "%0 is not valid on %1s in %select{classes|class-bound protocols}2"
33543354

33553355
- id: functions_mutating_and_not
33563356
msg: "method must not be declared both %0 and %1"

test/Sema/immutability.swift

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,13 @@ class FooClass {
6161

6262
mutating init(a : Bool) {} // expected-error {{'mutating' may only be used on 'func' declarations}} {{3-12=}}
6363

64-
mutating // expected-error {{'mutating' isn't valid on methods in classes or class-bound protocols}} {{3-12=}}
64+
mutating // expected-error {{'mutating' is not valid on instance methods in classes}} {{3-12=}}
6565
func baz() {}
6666

67-
nonmutating // expected-error {{'nonmutating' isn't valid on methods in classes or class-bound protocols}} {{3-15=}}
67+
nonmutating // expected-error {{'nonmutating' is not valid on instance methods in classes}} {{3-15=}}
6868
func bay() {}
6969

70-
mutating nonmutating // expected-error {{'mutating' isn't valid on methods in classes or class-bound protocols}} expected-error {{'nonmutating' isn't valid on methods in classes or class-bound protocols}}
70+
mutating nonmutating // expected-error {{'mutating' is not valid on instance methods in classes}} expected-error {{'nonmutating' is not valid on instance methods in classes}}
7171
func bax() {}
7272

7373
var x : Int {
@@ -86,6 +86,15 @@ class FooClass {
8686
}
8787
}
8888

89+
var computed: Int {
90+
mutating get { 0 } // expected-error {{'mutating' is not valid on getters in classes}} {{5-14=}}
91+
nonmutating set {} // expected-error {{'nonmutating' is not valid on setters in classes}} {{5-17=}}
92+
}
93+
94+
var storedWithObservers: Int = 0 {
95+
mutating willSet {} // expected-error {{'mutating' is not valid on willSet observers in classes}} {{5-14=}}
96+
nonmutating didSet {} // expected-error {{'nonmutating' is not valid on didSet observers in classes}} {{5-17=}}
97+
}
8998
}
9099

91100

@@ -241,7 +250,7 @@ func test_arguments(_ a : Int,
241250

242251

243252
protocol ClassBoundProtocolMutating : class {
244-
mutating // expected-error {{'mutating' isn't valid on methods in classes or class-bound protocols}} {{3-12=}}
253+
mutating // expected-error {{'mutating' is not valid on instance methods in class-bound protocols}} {{3-12=}}
245254
func f()
246255
}
247256

test/decl/ext/extensions.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -267,14 +267,14 @@ extension ImposeClassReq1 where Self: AnyObject {
267267

268268
var wrappingProperty2: Int {
269269
get { return someProperty }
270-
mutating set { someProperty = newValue } // expected-error {{'mutating' isn't valid on methods in classes or class-bound protocols}}
270+
mutating set { someProperty = newValue } // expected-error {{'mutating' is not valid on setters in class-bound protocols}}
271271
}
272272

273-
mutating func foo() { // expected-error {{mutating' isn't valid on methods in classes or class-bound protocols}}
273+
mutating func foo() { // expected-error {{mutating' is not valid on instance methods in class-bound protocols}}
274274
someProperty = 1
275275
}
276276

277-
nonmutating func bar() { // expected-error {{'nonmutating' isn't valid on methods in classes or class-bound protocols}}
277+
nonmutating func bar() { // expected-error {{'nonmutating' is not valid on instance methods in class-bound protocols}}
278278
someProperty = 2
279279
}
280280

@@ -309,14 +309,14 @@ extension ImposeClassReq2 {
309309

310310
var wrappingProperty2: Int {
311311
get { return someProperty }
312-
mutating set { someProperty = newValue } // expected-error {{'mutating' isn't valid on methods in classes or class-bound protocols}}
312+
mutating set { someProperty = newValue } // expected-error {{'mutating' is not valid on setters in class-bound protocols}}
313313
}
314314

315-
mutating func foo() { // expected-error {{mutating' isn't valid on methods in classes or class-bound protocols}}
315+
mutating func foo() { // expected-error {{mutating' is not valid on instance methods in class-bound protocols}}
316316
someProperty = 1
317317
}
318318

319-
nonmutating func bar() { // expected-error {{'nonmutating' isn't valid on methods in classes or class-bound protocols}}
319+
nonmutating func bar() { // expected-error {{'nonmutating' is not valid on instance methods in class-bound protocols}}
320320
someProperty = 2
321321
}
322322

0 commit comments

Comments
 (0)