Skip to content

Commit 22061e6

Browse files
committed
[Sema] InitAccessors: Verify that a property never appears both in initializes(...) and accesses(...)
1 parent fb15b6f commit 22061e6

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7289,6 +7289,9 @@ ERROR(init_accessor_initializes_attribute_on_other_declaration,none,
72897289
ERROR(init_accessor_accesses_attribute_on_other_declaration,none,
72907290
"accesses(...) attribute could only be used with init accessors",
72917291
())
7292+
ERROR(init_accessor_property_both_init_and_accessed,none,
7293+
"property %0 cannot be both initialized and accessed",
7294+
(DeclName))
72927295

72937296

72947297
#define UNDEFINE_DIAGNOSTIC_MACROS

lib/Sema/TypeCheckAttr.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3569,7 +3569,23 @@ void AttributeChecker::visitAccessesAttr(AccessesAttr *attr) {
35693569
return;
35703570
}
35713571

3572-
(void)attr->getPropertyDecls(accessor);
3572+
// Check whether there are any intersections between initializes(...) and
3573+
// accesses(...) attributes.
3574+
3575+
Optional<ArrayRef<VarDecl *>> initializedProperties;
3576+
if (auto *initAttr = D->getAttrs().getAttribute<InitializesAttr>()) {
3577+
initializedProperties.emplace(initAttr->getPropertyDecls(accessor));
3578+
}
3579+
3580+
if (initializedProperties) {
3581+
for (auto *property : attr->getPropertyDecls(accessor)) {
3582+
if (llvm::is_contained(*initializedProperties, property)) {
3583+
diagnose(attr->getLocation(),
3584+
diag::init_accessor_property_both_init_and_accessed,
3585+
property->getName());
3586+
}
3587+
}
3588+
}
35733589
}
35743590

35753591
void AttributeChecker::visitImplementsAttr(ImplementsAttr *attr) {

test/decl/var/init_accessors.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,33 @@ func test_assignment_to_let_properties() {
8484
}
8585
}
8686
}
87+
88+
func test_duplicate_and_computed_lazy_properties() {
89+
struct Test1 {
90+
var _a: Int
91+
var _b: Int
92+
93+
var a: Int {
94+
init(initialValue) initializes(_b _a) accesses(_a) {
95+
// expected-error@-1 {{property '_a' cannot be both initialized and accessed}}
96+
}
97+
}
98+
}
99+
100+
struct Test2 {
101+
var _a: Int
102+
103+
var a: Int {
104+
init(initialValue) initializes(a c) accesses(_a b) {}
105+
// expected-error@-1 {{init accessor cannot refer to property 'a'; init accessors can refer only to stored properties}}
106+
// expected-error@-2 {{init accessor cannot refer to property 'b'; init accessors can refer only to stored properties}}
107+
// expected-error@-3 {{init accessor cannot refer to property 'c'; init accessors can refer only to stored properties}}
108+
}
109+
110+
var b: Int {
111+
get { 42 }
112+
}
113+
114+
lazy var c: Int = 42
115+
}
116+
}

0 commit comments

Comments
 (0)