Skip to content

Commit 69302f9

Browse files
authored
Merge pull request #79655 from DougGregor/se-0458-condfails
[SE-0458] Improve backward compatibility of generated Swift interfaces
2 parents f55964d + ae6ae33 commit 69302f9

File tree

4 files changed

+52
-7
lines changed

4 files changed

+52
-7
lines changed

lib/AST/ASTPrinter.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2901,14 +2901,12 @@ void PrintAST::printInherited(const Decl *decl) {
29012901
Printer << "@preconcurrency ";
29022902
switch (inherited.getExplicitSafety()) {
29032903
case ExplicitSafety::Unspecified:
2904-
break;
2905-
29062904
case ExplicitSafety::Safe:
2907-
Printer << "@safe ";
29082905
break;
29092906

29102907
case ExplicitSafety::Unsafe:
2911-
Printer << "@unsafe ";
2908+
if (!llvm::is_contained(Options.ExcludeAttrList, TypeAttrKind::Unsafe))
2909+
Printer << "@unsafe ";
29122910
break;
29132911
}
29142912
if (inherited.isSuppressed())
@@ -3218,6 +3216,12 @@ suppressingFeatureMemorySafetyAttributes(PrintOptions &options,
32183216
llvm::function_ref<void()> action) {
32193217
ExcludeAttrRAII scope(options.ExcludeAttrList, DeclAttrKind::Unsafe);
32203218
ExcludeAttrRAII scope2(options.ExcludeAttrList, DeclAttrKind::Safe);
3219+
options.ExcludeAttrList.push_back(TypeAttrKind::Unsafe);
3220+
SWIFT_DEFER {
3221+
assert(options.ExcludeAttrList.back() == TypeAttrKind::Unsafe);
3222+
options.ExcludeAttrList.pop_back();
3223+
};
3224+
32213225
action();
32223226
}
32233227

lib/AST/FeatureSet.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/AST/NameLookup.h"
1919
#include "swift/AST/ParameterList.h"
2020
#include "swift/AST/Pattern.h"
21+
#include "swift/AST/ProtocolConformance.h"
2122
#include "clang/AST/DeclObjC.h"
2223
#include "swift/Basic/Assertions.h"
2324

@@ -350,8 +351,32 @@ static bool usesFeatureIsolatedConformances(Decl *decl) {
350351
}
351352

352353
static bool usesFeatureMemorySafetyAttributes(Decl *decl) {
353-
return decl->getAttrs().hasAttribute<SafeAttr>() ||
354-
decl->getAttrs().hasAttribute<UnsafeAttr>();
354+
if (decl->getAttrs().hasAttribute<SafeAttr>() ||
355+
decl->getAttrs().hasAttribute<UnsafeAttr>())
356+
return true;
357+
358+
IterableDeclContext *idc;
359+
if (auto nominal = dyn_cast<NominalTypeDecl>(decl))
360+
idc = nominal;
361+
else if (auto ext = dyn_cast<ExtensionDecl>(decl))
362+
idc = ext;
363+
else
364+
idc = nullptr;
365+
366+
// Look for an @unsafe conformance ascribed to this declaration.
367+
if (idc) {
368+
auto conformances = idc->getLocalConformances();
369+
for (auto conformance : conformances) {
370+
auto rootConformance = conformance->getRootConformance();
371+
if (auto rootNormalConformance =
372+
dyn_cast<NormalProtocolConformance>(rootConformance)) {
373+
if (rootNormalConformance->getExplicitSafety() == ExplicitSafety::Unsafe)
374+
return true;
375+
}
376+
}
377+
}
378+
379+
return false;
355380
}
356381

357382
UNINTERESTING_FEATURE(StrictMemorySafety)

lib/ASTGen/Sources/ASTGen/CompilerBuildConfiguration.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,10 @@ fileprivate class RemoveUnsafeExprSyntaxRewriter: SyntaxRewriter {
552552
override func visit(_ node: UnsafeExprSyntax) -> ExprSyntax {
553553
return node.expression.with(\.leadingTrivia, node.leadingTrivia)
554554
}
555+
556+
override func visit(_ node: ForStmtSyntax) -> StmtSyntax {
557+
return StmtSyntax(node.with(\.unsafeKeyword, nil))
558+
}
555559
}
556560

557561
extension SyntaxProtocol {

test/Unsafe/module-interface.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,34 @@
99
// CHECK: #endif
1010
@unsafe public func getIntUnsafely() -> Int { 0 }
1111

12+
public struct UnsafeIterator: @unsafe IteratorProtocol {
13+
@unsafe public mutating func next() -> Int? { nil }
14+
}
15+
16+
public struct SequenceWithUnsafeIterator: Sequence {
17+
public init() { }
18+
public func makeIterator() -> UnsafeIterator { UnsafeIterator() }
19+
}
20+
1221
// CHECK: @inlinable public func useUnsafeCode()
1322
@inlinable public func useUnsafeCode() {
1423
// CHECK-NOT: unsafe
1524
print( unsafe getIntUnsafely())
25+
26+
for unsafe _ in SequenceWithUnsafeIterator() { }
1627
}
1728

1829
// CHECK: public protocol P
1930
public protocol P {
2031
func f()
2132
}
2233

34+
// CHECK: #if compiler(>=5.3) && $MemorySafetyAttributes
2335
// CHECK: public struct X : @unsafe UserModule.P
2436
public struct X: @unsafe P {
25-
// CHECK: #if compiler(>=5.3) && $MemorySafetyAttributes
2637
// CHECK: @unsafe public func f()
2738
// CHECK: #else
39+
// CHECK: public struct X : UserModule.P
2840
// CHECK: public func f()
2941
// CHECK: #endif
3042
@unsafe public func f() { }

0 commit comments

Comments
 (0)