Skip to content

Commit 983046f

Browse files
committed
[SE-0458] Suppress @unsafe conformances for compilers that can't handle them
1 parent fa86097 commit 983046f

File tree

3 files changed

+37
-7
lines changed

3 files changed

+37
-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)

test/Unsafe/module-interface.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ public protocol P {
2020
func f()
2121
}
2222

23+
// CHECK: #if compiler(>=5.3) && $MemorySafetyAttributes
2324
// CHECK: public struct X : @unsafe UserModule.P
2425
public struct X: @unsafe P {
25-
// CHECK: #if compiler(>=5.3) && $MemorySafetyAttributes
2626
// CHECK: @unsafe public func f()
2727
// CHECK: #else
28+
// CHECK: public struct X : UserModule.P
2829
// CHECK: public func f()
2930
// CHECK: #endif
3031
@unsafe public func f() { }

0 commit comments

Comments
 (0)