Skip to content

Commit 110c843

Browse files
authored
Merge pull request #11979 from slavapestov/versioned-attr-fixes
Fixes for @_versioned attribute
2 parents 875435d + 10bd85c commit 110c843

8 files changed

+44
-20
lines changed

lib/Sema/DerivedConformanceCodable.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -802,8 +802,7 @@ static FuncDecl *deriveEncodable_encode(TypeChecker &tc, Decl *parentDecl,
802802
}
803803

804804
encodeDecl->setInterfaceType(interfaceType);
805-
encodeDecl->setAccess(std::max(target->getFormalAccess(),
806-
AccessLevel::Internal));
805+
encodeDecl->setAccess(target->getFormalAccess());
807806

808807
// If the type was not imported, the derived conformance is either from the
809808
// type itself or an extension, in which case we will emit the declaration
@@ -1149,8 +1148,7 @@ static ValueDecl *deriveDecodable_init(TypeChecker &tc, Decl *parentDecl,
11491148

11501149
initDecl->setInterfaceType(interfaceType);
11511150
initDecl->setInitializerInterfaceType(initializerType);
1152-
initDecl->setAccess(std::max(target->getFormalAccess(),
1153-
AccessLevel::Internal));
1151+
initDecl->setAccess(target->getFormalAccess());
11541152

11551153
// If the type was not imported, the derived conformance is either from the
11561154
// type itself or an extension, in which case we will emit the declaration

lib/Sema/DerivedConformanceCodingKey.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,7 @@ static ValueDecl *deriveInitDecl(TypeChecker &tc, Decl *parentDecl,
181181
}
182182
initDecl->setInterfaceType(allocIfaceType);
183183
initDecl->setInitializerInterfaceType(initIfaceType);
184-
initDecl->setAccess(std::max(AccessLevel::Internal,
185-
enumDecl->getFormalAccess()));
184+
initDecl->setAccess(enumDecl->getFormalAccess());
186185

187186
// If the enum was not imported, the derived conformance is either from the
188187
// enum itself or an extension, in which case we will emit the declaration

lib/Sema/DerivedConformanceEquatableHashable.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,7 @@ deriveEquatable_enum_eq(TypeChecker &tc, Decl *parentDecl, EnumDecl *enumDecl) {
296296
FunctionType::ExtInfo());
297297
}
298298
eqDecl->setInterfaceType(interfaceTy);
299-
300-
// Since we can't insert the == operator into the same FileUnit as the enum,
301-
// itself, we have to give it at least internal access.
302-
eqDecl->setAccess(std::max(enumDecl->getFormalAccess(),
303-
AccessLevel::Internal));
299+
copyFormalAccess(eqDecl, enumDecl);
304300

305301
// If the enum was not imported, the derived conformance is either from the
306302
// enum itself or an extension, in which case we will emit the declaration
@@ -430,8 +426,7 @@ deriveHashable_enum_hashValue(TypeChecker &tc, Decl *parentDecl,
430426
AnyFunctionType::ExtInfo());
431427

432428
getterDecl->setInterfaceType(interfaceType);
433-
getterDecl->setAccess(std::max(AccessLevel::Internal,
434-
enumDecl->getFormalAccess()));
429+
copyFormalAccess(getterDecl, enumDecl);
435430

436431
// If the enum was not imported, the derived conformance is either from the
437432
// enum itself or an extension, in which case we will emit the declaration
@@ -447,7 +442,7 @@ deriveHashable_enum_hashValue(TypeChecker &tc, Decl *parentDecl,
447442
hashValueDecl->setInterfaceType(intType);
448443
hashValueDecl->makeComputed(SourceLoc(), getterDecl,
449444
nullptr, nullptr, SourceLoc());
450-
hashValueDecl->setAccess(getterDecl->getFormalAccess());
445+
copyFormalAccess(hashValueDecl, enumDecl);
451446

452447
Pattern *hashValuePat = new (C) NamedPattern(hashValueDecl, /*implicit*/true);
453448
hashValuePat->setType(intType);

lib/Sema/DerivedConformanceRawRepresentable.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,7 @@ static ConstructorDecl *deriveRawRepresentable_init(TypeChecker &tc,
318318
}
319319
initDecl->setInterfaceType(allocIfaceType);
320320
initDecl->setInitializerInterfaceType(initIfaceType);
321-
initDecl->setAccess(std::max(AccessLevel::Internal,
322-
enumDecl->getFormalAccess()));
321+
copyFormalAccess(initDecl, enumDecl);
323322

324323
// If the enum was not imported, the derived conformance is either from the
325324
// enum itself or an extension, in which case we will emit the declaration

lib/Sema/DerivedConformances.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,7 @@ FuncDecl *DerivedConformance::declareDerivedPropertyGetter(TypeChecker &tc,
171171
interfaceType = FunctionType::get({selfParam}, interfaceType,
172172
FunctionType::ExtInfo());
173173
getterDecl->setInterfaceType(interfaceType);
174-
getterDecl->setAccess(std::max(typeDecl->getFormalAccess(),
175-
AccessLevel::Internal));
174+
copyFormalAccess(getterDecl, typeDecl);
176175

177176
// If the enum was not imported, the derived conformance is either from the
178177
// enum itself or an extension, in which case we will emit the declaration
@@ -202,7 +201,7 @@ DerivedConformance::declareDerivedReadOnlyProperty(TypeChecker &tc,
202201
propDecl->setImplicit();
203202
propDecl->makeComputed(SourceLoc(), getterDecl, nullptr, nullptr,
204203
SourceLoc());
205-
propDecl->setAccess(getterDecl->getFormalAccess());
204+
copyFormalAccess(propDecl, typeDecl);
206205
propDecl->setInterfaceType(propertyInterfaceType);
207206

208207
// If this is supposed to be a final property, mark it as such.
@@ -225,3 +224,14 @@ DerivedConformance::declareDerivedReadOnlyProperty(TypeChecker &tc,
225224

226225
return {propDecl, pbDecl};
227226
}
227+
228+
void DerivedConformance::copyFormalAccess(ValueDecl *dest, ValueDecl *source) {
229+
dest->setAccess(source->getFormalAccess());
230+
231+
// Inherit the @_versioned attribute.
232+
if (source->getAttrs().hasAttribute<VersionedAttr>()) {
233+
auto &ctx = source->getASTContext();
234+
auto *clonedAttr = new (ctx) VersionedAttr(/*implicit=*/true);
235+
dest->getAttrs().add(clonedAttr);
236+
}
237+
}

lib/Sema/DerivedConformances.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ declareDerivedReadOnlyProperty(TypeChecker &tc,
145145
/// Build a reference to the 'self' decl of a derived function.
146146
DeclRefExpr *createSelfDeclRef(AbstractFunctionDecl *fn);
147147

148+
/// Copy access from the source decl to the destination decl.
149+
void copyFormalAccess(ValueDecl *dest, ValueDecl *source);
150+
148151
}
149152

150153
}

test/attr/accessibility_print.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ private enum DA_PrivateEnum {
9494
case Foo, Bar
9595
// CHECK: internal init()
9696
init() { self = .Foo }
97-
// CHECK: internal var hashValue
97+
// CHECK: private var hashValue
9898
} // CHECK: {{^[}]}}
9999

100100
// CHECK-LABEL: internal{{(\*/)?}} enum DB_InternalEnum {

test/attr/attr_versioned.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,23 @@ protocol VersionedProtocol {
4545
@_versioned func versionedRequirement() -> T
4646
// expected-error@-1 {{'@_versioned' attribute cannot be used in protocols}}
4747
}
48+
49+
// Derived conformances had issues with @_versioned - rdar://problem/34342955
50+
@_versioned
51+
internal enum EqEnum {
52+
case foo
53+
}
54+
55+
@_versioned
56+
internal enum RawEnum : Int {
57+
case foo = 0
58+
}
59+
60+
@_inlineable
61+
public func usesEqEnum() -> Bool {
62+
_ = (EqEnum.foo == .foo)
63+
_ = EqEnum.foo.hashValue
64+
65+
_ = RawEnum.foo.rawValue
66+
_ = RawEnum(rawValue: 0)
67+
}

0 commit comments

Comments
 (0)