Skip to content

Commit 930f58a

Browse files
committed
Sema: Skip storage diagnostic for @exclusivity in swiftinterfaces.
Relax the diagnostics for the `@exclusivity` attribute in order to avoid type checking failures for `public private(set)` properties in resilient libraries. In a `swiftinterface` it's not possible to tell reliably whether a property has storage. Resolves rdar://107770440
1 parent e117604 commit 930f58a

File tree

2 files changed

+59
-11
lines changed

2 files changed

+59
-11
lines changed

lib/Sema/TypeCheckAttr.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2962,22 +2962,27 @@ void AttributeChecker::visitOptimizeAttr(OptimizeAttr *attr) {
29622962

29632963
void AttributeChecker::visitExclusivityAttr(ExclusivityAttr *attr) {
29642964
if (auto *varDecl = dyn_cast<VarDecl>(D)) {
2965-
if (!varDecl->hasStorage()) {
2966-
diagnose(attr->getLocation(), diag::exclusivity_on_computed_property);
2967-
attr->setInvalid();
2968-
return;
2965+
auto *DC = D->getDeclContext();
2966+
auto *parentSF = DC->getParentSourceFile();
2967+
2968+
if (parentSF && parentSF->Kind != SourceFileKind::Interface) {
2969+
if (!varDecl->hasStorage()) {
2970+
diagnose(attr->getLocation(), diag::exclusivity_on_computed_property);
2971+
attr->setInvalid();
2972+
return;
2973+
}
29692974
}
2970-
2971-
if (isa<ClassDecl>(varDecl->getDeclContext()))
2975+
2976+
if (isa<ClassDecl>(DC))
29722977
return;
2973-
2974-
if (varDecl->getDeclContext()->isTypeContext() && !varDecl->isInstanceMember())
2978+
2979+
if (DC->isTypeContext() && !varDecl->isInstanceMember())
29752980
return;
2976-
2977-
if (varDecl->getDeclContext()->isModuleScopeContext())
2981+
2982+
if (DC->isModuleScopeContext())
29782983
return;
29792984
}
2980-
diagnose(attr->getLocation(), diag::exclusivity_on_wrong_decl);
2985+
diagnoseAndRemoveAttr(attr, diag::exclusivity_on_wrong_decl);
29812986
attr->setInvalid();
29822987
}
29832988

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s -module-name exclusivity
2+
// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -module-name exclusivity
3+
// RUN: %FileCheck %s < %t.swiftinterface
4+
5+
// CHECK: @exclusivity(checked) public var checkedGlobalVar: Swift.Int
6+
@exclusivity(checked)
7+
public var checkedGlobalVar = 1
8+
9+
// CHECK: @exclusivity(unchecked) public var uncheckedGlobalVar: Swift.Int
10+
@exclusivity(unchecked)
11+
public var uncheckedGlobalVar = 1
12+
13+
// CHECK-LABEL: public struct Struct
14+
public struct Struct {
15+
// CHECK: @exclusivity(unchecked) public static var uncheckedStaticVar: Swift.Int
16+
@exclusivity(unchecked)
17+
public static var uncheckedStaticVar: Int = 27
18+
19+
// CHECK: @exclusivity(checked) public static var checkedStaticVar: Swift.Int
20+
@exclusivity(checked)
21+
public static var checkedStaticVar: Int = 27
22+
}
23+
24+
// CHECK-LABEL: public class Class
25+
public class Class {
26+
// CHECK: @exclusivity(unchecked) public var uncheckedInstanceVar: Swift.Int
27+
@exclusivity(unchecked)
28+
public var uncheckedInstanceVar: Int = 27
29+
30+
// CHECK: @exclusivity(checked) public var checkedInstanceVar: Swift.Int
31+
@exclusivity(checked)
32+
public var checkedInstanceVar: Int = 27
33+
34+
// CHECK: @exclusivity(unchecked) public var uncheckedPrivateSetInstanceVar: Swift.Int {
35+
// CHECK-NEXT: get
36+
// CHECK-NEXT: }
37+
@exclusivity(unchecked)
38+
public private(set) var uncheckedPrivateSetInstanceVar: Int = 27
39+
40+
// CHECK: @exclusivity(unchecked) public static var uncheckedStaticVar: Swift.Int
41+
@exclusivity(unchecked)
42+
public static var uncheckedStaticVar: Int = 27
43+
}

0 commit comments

Comments
 (0)