Merge pull request #11979 from slavapestov/versioned-attr-fixes
Fixes for @_versioned attribute
diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp
index b3a53f1..a0b6b10 100644
--- a/lib/Sema/DerivedConformanceCodable.cpp
+++ b/lib/Sema/DerivedConformanceCodable.cpp
@@ -802,8 +802,7 @@
}
encodeDecl->setInterfaceType(interfaceType);
- encodeDecl->setAccess(std::max(target->getFormalAccess(),
- AccessLevel::Internal));
+ encodeDecl->setAccess(target->getFormalAccess());
// If the type was not imported, the derived conformance is either from the
// type itself or an extension, in which case we will emit the declaration
@@ -1149,8 +1148,7 @@
initDecl->setInterfaceType(interfaceType);
initDecl->setInitializerInterfaceType(initializerType);
- initDecl->setAccess(std::max(target->getFormalAccess(),
- AccessLevel::Internal));
+ initDecl->setAccess(target->getFormalAccess());
// If the type was not imported, the derived conformance is either from the
// type itself or an extension, in which case we will emit the declaration
diff --git a/lib/Sema/DerivedConformanceCodingKey.cpp b/lib/Sema/DerivedConformanceCodingKey.cpp
index f9d0edc..8293912 100644
--- a/lib/Sema/DerivedConformanceCodingKey.cpp
+++ b/lib/Sema/DerivedConformanceCodingKey.cpp
@@ -181,8 +181,7 @@
}
initDecl->setInterfaceType(allocIfaceType);
initDecl->setInitializerInterfaceType(initIfaceType);
- initDecl->setAccess(std::max(AccessLevel::Internal,
- enumDecl->getFormalAccess()));
+ initDecl->setAccess(enumDecl->getFormalAccess());
// If the enum was not imported, the derived conformance is either from the
// enum itself or an extension, in which case we will emit the declaration
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index 746edbf..95578b2 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -296,11 +296,7 @@
FunctionType::ExtInfo());
}
eqDecl->setInterfaceType(interfaceTy);
-
- // Since we can't insert the == operator into the same FileUnit as the enum,
- // itself, we have to give it at least internal access.
- eqDecl->setAccess(std::max(enumDecl->getFormalAccess(),
- AccessLevel::Internal));
+ copyFormalAccess(eqDecl, enumDecl);
// If the enum was not imported, the derived conformance is either from the
// enum itself or an extension, in which case we will emit the declaration
@@ -430,8 +426,7 @@
AnyFunctionType::ExtInfo());
getterDecl->setInterfaceType(interfaceType);
- getterDecl->setAccess(std::max(AccessLevel::Internal,
- enumDecl->getFormalAccess()));
+ copyFormalAccess(getterDecl, enumDecl);
// If the enum was not imported, the derived conformance is either from the
// enum itself or an extension, in which case we will emit the declaration
@@ -447,7 +442,7 @@
hashValueDecl->setInterfaceType(intType);
hashValueDecl->makeComputed(SourceLoc(), getterDecl,
nullptr, nullptr, SourceLoc());
- hashValueDecl->setAccess(getterDecl->getFormalAccess());
+ copyFormalAccess(hashValueDecl, enumDecl);
Pattern *hashValuePat = new (C) NamedPattern(hashValueDecl, /*implicit*/true);
hashValuePat->setType(intType);
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index a17f4e6..1c94786 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -318,8 +318,7 @@
}
initDecl->setInterfaceType(allocIfaceType);
initDecl->setInitializerInterfaceType(initIfaceType);
- initDecl->setAccess(std::max(AccessLevel::Internal,
- enumDecl->getFormalAccess()));
+ copyFormalAccess(initDecl, enumDecl);
// If the enum was not imported, the derived conformance is either from the
// enum itself or an extension, in which case we will emit the declaration
diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp
index 8506b5a..f3a4033 100644
--- a/lib/Sema/DerivedConformances.cpp
+++ b/lib/Sema/DerivedConformances.cpp
@@ -171,8 +171,7 @@
interfaceType = FunctionType::get({selfParam}, interfaceType,
FunctionType::ExtInfo());
getterDecl->setInterfaceType(interfaceType);
- getterDecl->setAccess(std::max(typeDecl->getFormalAccess(),
- AccessLevel::Internal));
+ copyFormalAccess(getterDecl, typeDecl);
// If the enum was not imported, the derived conformance is either from the
// enum itself or an extension, in which case we will emit the declaration
@@ -202,7 +201,7 @@
propDecl->setImplicit();
propDecl->makeComputed(SourceLoc(), getterDecl, nullptr, nullptr,
SourceLoc());
- propDecl->setAccess(getterDecl->getFormalAccess());
+ copyFormalAccess(propDecl, typeDecl);
propDecl->setInterfaceType(propertyInterfaceType);
// If this is supposed to be a final property, mark it as such.
@@ -225,3 +224,14 @@
return {propDecl, pbDecl};
}
+
+void DerivedConformance::copyFormalAccess(ValueDecl *dest, ValueDecl *source) {
+ dest->setAccess(source->getFormalAccess());
+
+ // Inherit the @_versioned attribute.
+ if (source->getAttrs().hasAttribute<VersionedAttr>()) {
+ auto &ctx = source->getASTContext();
+ auto *clonedAttr = new (ctx) VersionedAttr(/*implicit=*/true);
+ dest->getAttrs().add(clonedAttr);
+ }
+}
diff --git a/lib/Sema/DerivedConformances.h b/lib/Sema/DerivedConformances.h
index 9b56a26..1d78a86 100644
--- a/lib/Sema/DerivedConformances.h
+++ b/lib/Sema/DerivedConformances.h
@@ -145,6 +145,9 @@
/// Build a reference to the 'self' decl of a derived function.
DeclRefExpr *createSelfDeclRef(AbstractFunctionDecl *fn);
+/// Copy access from the source decl to the destination decl.
+void copyFormalAccess(ValueDecl *dest, ValueDecl *source);
+
}
}
diff --git a/test/attr/accessibility_print.swift b/test/attr/accessibility_print.swift
index b4eb3a1..2785b7e 100644
--- a/test/attr/accessibility_print.swift
+++ b/test/attr/accessibility_print.swift
@@ -94,7 +94,7 @@
case Foo, Bar
// CHECK: internal init()
init() { self = .Foo }
- // CHECK: internal var hashValue
+ // CHECK: private var hashValue
} // CHECK: {{^[}]}}
// CHECK-LABEL: internal{{(\*/)?}} enum DB_InternalEnum {
diff --git a/test/attr/attr_versioned.swift b/test/attr/attr_versioned.swift
index 1a5682e..3a6fe43 100644
--- a/test/attr/attr_versioned.swift
+++ b/test/attr/attr_versioned.swift
@@ -45,3 +45,23 @@
@_versioned func versionedRequirement() -> T
// expected-error@-1 {{'@_versioned' attribute cannot be used in protocols}}
}
+
+// Derived conformances had issues with @_versioned - rdar://problem/34342955
+@_versioned
+internal enum EqEnum {
+ case foo
+}
+
+@_versioned
+internal enum RawEnum : Int {
+ case foo = 0
+}
+
+@_inlineable
+public func usesEqEnum() -> Bool {
+ _ = (EqEnum.foo == .foo)
+ _ = EqEnum.foo.hashValue
+
+ _ = RawEnum.foo.rawValue
+ _ = RawEnum(rawValue: 0)
+}