mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #79655 from DougGregor/se-0458-condfails
[SE-0458] Improve backward compatibility of generated Swift interfaces
This commit is contained in:
@@ -2901,14 +2901,12 @@ void PrintAST::printInherited(const Decl *decl) {
|
||||
Printer << "@preconcurrency ";
|
||||
switch (inherited.getExplicitSafety()) {
|
||||
case ExplicitSafety::Unspecified:
|
||||
break;
|
||||
|
||||
case ExplicitSafety::Safe:
|
||||
Printer << "@safe ";
|
||||
break;
|
||||
|
||||
case ExplicitSafety::Unsafe:
|
||||
Printer << "@unsafe ";
|
||||
if (!llvm::is_contained(Options.ExcludeAttrList, TypeAttrKind::Unsafe))
|
||||
Printer << "@unsafe ";
|
||||
break;
|
||||
}
|
||||
if (inherited.isSuppressed())
|
||||
@@ -3218,6 +3216,12 @@ suppressingFeatureMemorySafetyAttributes(PrintOptions &options,
|
||||
llvm::function_ref<void()> action) {
|
||||
ExcludeAttrRAII scope(options.ExcludeAttrList, DeclAttrKind::Unsafe);
|
||||
ExcludeAttrRAII scope2(options.ExcludeAttrList, DeclAttrKind::Safe);
|
||||
options.ExcludeAttrList.push_back(TypeAttrKind::Unsafe);
|
||||
SWIFT_DEFER {
|
||||
assert(options.ExcludeAttrList.back() == TypeAttrKind::Unsafe);
|
||||
options.ExcludeAttrList.pop_back();
|
||||
};
|
||||
|
||||
action();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "swift/AST/NameLookup.h"
|
||||
#include "swift/AST/ParameterList.h"
|
||||
#include "swift/AST/Pattern.h"
|
||||
#include "swift/AST/ProtocolConformance.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "swift/Basic/Assertions.h"
|
||||
|
||||
@@ -350,8 +351,32 @@ static bool usesFeatureIsolatedConformances(Decl *decl) {
|
||||
}
|
||||
|
||||
static bool usesFeatureMemorySafetyAttributes(Decl *decl) {
|
||||
return decl->getAttrs().hasAttribute<SafeAttr>() ||
|
||||
decl->getAttrs().hasAttribute<UnsafeAttr>();
|
||||
if (decl->getAttrs().hasAttribute<SafeAttr>() ||
|
||||
decl->getAttrs().hasAttribute<UnsafeAttr>())
|
||||
return true;
|
||||
|
||||
IterableDeclContext *idc;
|
||||
if (auto nominal = dyn_cast<NominalTypeDecl>(decl))
|
||||
idc = nominal;
|
||||
else if (auto ext = dyn_cast<ExtensionDecl>(decl))
|
||||
idc = ext;
|
||||
else
|
||||
idc = nullptr;
|
||||
|
||||
// Look for an @unsafe conformance ascribed to this declaration.
|
||||
if (idc) {
|
||||
auto conformances = idc->getLocalConformances();
|
||||
for (auto conformance : conformances) {
|
||||
auto rootConformance = conformance->getRootConformance();
|
||||
if (auto rootNormalConformance =
|
||||
dyn_cast<NormalProtocolConformance>(rootConformance)) {
|
||||
if (rootNormalConformance->getExplicitSafety() == ExplicitSafety::Unsafe)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
UNINTERESTING_FEATURE(StrictMemorySafety)
|
||||
|
||||
@@ -552,6 +552,10 @@ fileprivate class RemoveUnsafeExprSyntaxRewriter: SyntaxRewriter {
|
||||
override func visit(_ node: UnsafeExprSyntax) -> ExprSyntax {
|
||||
return node.expression.with(\.leadingTrivia, node.leadingTrivia)
|
||||
}
|
||||
|
||||
override func visit(_ node: ForStmtSyntax) -> StmtSyntax {
|
||||
return StmtSyntax(node.with(\.unsafeKeyword, nil))
|
||||
}
|
||||
}
|
||||
|
||||
extension SyntaxProtocol {
|
||||
|
||||
@@ -9,10 +9,21 @@
|
||||
// CHECK: #endif
|
||||
@unsafe public func getIntUnsafely() -> Int { 0 }
|
||||
|
||||
public struct UnsafeIterator: @unsafe IteratorProtocol {
|
||||
@unsafe public mutating func next() -> Int? { nil }
|
||||
}
|
||||
|
||||
public struct SequenceWithUnsafeIterator: Sequence {
|
||||
public init() { }
|
||||
public func makeIterator() -> UnsafeIterator { UnsafeIterator() }
|
||||
}
|
||||
|
||||
// CHECK: @inlinable public func useUnsafeCode()
|
||||
@inlinable public func useUnsafeCode() {
|
||||
// CHECK-NOT: unsafe
|
||||
print( unsafe getIntUnsafely())
|
||||
|
||||
for unsafe _ in SequenceWithUnsafeIterator() { }
|
||||
}
|
||||
|
||||
// CHECK: public protocol P
|
||||
@@ -20,11 +31,12 @@ public protocol P {
|
||||
func f()
|
||||
}
|
||||
|
||||
// CHECK: #if compiler(>=5.3) && $MemorySafetyAttributes
|
||||
// CHECK: public struct X : @unsafe UserModule.P
|
||||
public struct X: @unsafe P {
|
||||
// CHECK: #if compiler(>=5.3) && $MemorySafetyAttributes
|
||||
// CHECK: @unsafe public func f()
|
||||
// CHECK: #else
|
||||
// CHECK: public struct X : UserModule.P
|
||||
// CHECK: public func f()
|
||||
// CHECK: #endif
|
||||
@unsafe public func f() { }
|
||||
|
||||
Reference in New Issue
Block a user