From 90a2b3d8a08867166807d25017b4d3600fc5ac1d Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 27 Mar 2025 09:49:34 -0700 Subject: [PATCH 1/6] Look through "unsafe" expressions when checking for single-value statements We were rejecting the use of switch expressions on the right-hand side of an assignment that was marked `unsafe`. Fixes rdar://147944753. --- lib/Sema/PreCheckTarget.cpp | 5 +++++ test/Unsafe/safe.swift | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/lib/Sema/PreCheckTarget.cpp b/lib/Sema/PreCheckTarget.cpp index ee7289b24ab40..0336f1f0636e0 100644 --- a/lib/Sema/PreCheckTarget.cpp +++ b/lib/Sema/PreCheckTarget.cpp @@ -1680,6 +1680,11 @@ void PreCheckTarget::markAnyValidSingleValueStmts(Expr *E) { while (auto *IIO = dyn_cast(E)) E = IIO->getSubExpr(); } + + // Look through "unsafe" expressions. + if (auto UE = dyn_cast(E)) + E = UE->getSubExpr(); + return dyn_cast(E); }; diff --git a/test/Unsafe/safe.swift b/test/Unsafe/safe.swift index 89bb918335151..681e3fb23bee1 100644 --- a/test/Unsafe/safe.swift +++ b/test/Unsafe/safe.swift @@ -241,3 +241,11 @@ func testMyArray(ints: MyArray) { unsafe print(buffer.unsafeCount) } } + +func testUnsafeLHS() { + @unsafe var value: Int = 0 + unsafe value = switch unsafe value { + case 0: 1 + default: 0 + } +} From d86f41a922269db32b83218f982b68f485f47033 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 27 Mar 2025 16:02:39 -0700 Subject: [PATCH 2/6] Improve Fix-It for `if let x` where `x` is a reference to an unsafe value When we encounter unsafe code in `if let x`, we would produce a Fix-It that would change it to the ill-formed `if let unsafe x`. Improve tracking of the expressions that are synthesized for the right-hand side of these conditions, so that we can produce a Fix-It that turns this into the proper if let x = unsafe x Fixes rdar://147944243. --- lib/Sema/TypeCheckEffects.cpp | 82 ++++++++++++++++++++++++++++--- test/Unsafe/safe.swift | 19 +++++++ test/expr/unary/async_await.swift | 2 +- 3 files changed, 94 insertions(+), 9 deletions(-) diff --git a/lib/Sema/TypeCheckEffects.cpp b/lib/Sema/TypeCheckEffects.cpp index a2cde1bd1962b..d2fc40c5069eb 100644 --- a/lib/Sema/TypeCheckEffects.cpp +++ b/lib/Sema/TypeCheckEffects.cpp @@ -668,7 +668,10 @@ class EffectsHandlingWalker : public ASTWalker { recurse = asImpl().checkThrow(thr); } else if (auto forEach = dyn_cast(S)) { recurse = asImpl().checkForEach(forEach); + } else if (auto labeled = dyn_cast(S)) { + asImpl().noteLabeledConditionalStmt(labeled); } + if (!recurse) return Action::SkipNode(S); @@ -690,6 +693,8 @@ class EffectsHandlingWalker : public ASTWalker { } void visitExprPre(Expr *expr) { asImpl().visitExprPre(expr); } + + void noteLabeledConditionalStmt(LabeledConditionalStmt *stmt) { } }; /// A potential reason why something might have an effect. @@ -3416,6 +3421,10 @@ class CheckEffectsCoverage : public EffectsHandlingWalker /// passed directly into an explicitly `@safe` function. llvm::DenseSet assumedSafeArguments; + /// Keeps track of the expressions that were synthesized as initializers for + /// the "if let x" shorthand syntax. + llvm::SmallPtrSet synthesizedIfLetInitializers; + /// Tracks all of the uncovered uses of unsafe constructs based on their /// anchor expression, so we can emit diagnostics at the end. llvm::MapVector> uncoveredUnsafeUses; @@ -4425,7 +4434,67 @@ class CheckEffectsCoverage : public EffectsHandlingWalker Ctx.Diags.diagnose(E->getUnsafeLoc(), diag::no_unsafe_in_unsafe) .fixItRemove(E->getUnsafeLoc()); } - + + void noteLabeledConditionalStmt(LabeledConditionalStmt *stmt) { + // Make a note of any initializers that are the synthesized right-hand side + // for an "if let x". + for (const auto &condition: stmt->getCond()) { + switch (condition.getKind()) { + case StmtConditionElement::CK_Availability: + case StmtConditionElement::CK_Boolean: + case StmtConditionElement::CK_HasSymbol: + continue; + + case StmtConditionElement::CK_PatternBinding: + break; + } + + auto init = condition.getInitializer(); + if (!init) + continue; + + auto pattern = condition.getPattern(); + if (!pattern) + continue; + + auto optPattern = dyn_cast(pattern); + if (!optPattern) + continue; + + auto var = optPattern->getSubPattern()->getSingleVar(); + if (!var) + continue; + + // If the right-hand side has the same location as the variable, it was + // synthesized. + if (var->getLoc().isValid() && + var->getLoc() == init->getStartLoc() && + init->getStartLoc() == init->getEndLoc()) + synthesizedIfLetInitializers.insert(init); + } + } + + /// Determine whether this is the synthesized right-hand-side when we have + /// expanded an "if let x" into its semantic equivalent, "if let x = x". + VarDecl *isShorthandIfLetSyntax(const Expr *expr) const { + // Check whether this is referencing a variable. + VarDecl *var = nullptr; + if (auto declRef = dyn_cast(expr)) { + var = dyn_cast_or_null(declRef->getDecl()); + } else if (auto memberRef = dyn_cast(expr)) { + var = dyn_cast_or_null(memberRef->getMember().getDecl()); + } + + if (!var) + return nullptr; + + // If we identified this as one of the bindings, return the variable. + if (synthesizedIfLetInitializers.contains(expr)) + return var; + + return nullptr; + } + std::pair getFixItForUncoveredSite(const Expr *anchor, StringRef keyword) const { SourceLoc insertLoc = anchor->getStartLoc(); @@ -4438,13 +4507,10 @@ class CheckEffectsCoverage : public EffectsHandlingWalker insertLoc = tryExpr->getSubExpr()->getStartLoc(); // Supply a tailored fixIt including the identifier if we are // looking at a shorthand optional binding. - } else if (anchor->isImplicit()) { - if (auto declRef = dyn_cast(anchor)) - if (auto var = dyn_cast_or_null(declRef->getDecl())) { - insertText = (" = " + keyword).str() + " " + var->getNameStr().str(); - insertLoc = Lexer::getLocForEndOfToken(Ctx.Diags.SourceMgr, - anchor->getStartLoc()); - } + } else if (auto var = isShorthandIfLetSyntax(anchor)) { + insertText = (" = " + keyword).str() + " " + var->getNameStr().str(); + insertLoc = Lexer::getLocForEndOfToken(Ctx.Diags.SourceMgr, + anchor->getStartLoc()); } return std::make_pair(insertLoc, insertText); } diff --git a/test/Unsafe/safe.swift b/test/Unsafe/safe.swift index 681e3fb23bee1..af7823bb2a02e 100644 --- a/test/Unsafe/safe.swift +++ b/test/Unsafe/safe.swift @@ -249,3 +249,22 @@ func testUnsafeLHS() { default: 0 } } + +@safe +struct UnsafeWrapTest { + @unsafe var pointer: UnsafeMutablePointer? + + func test() { + if let pointer { // expected-warning{{expression uses unsafe constructs but is not marked with 'unsafe'}}{{19-19= = unsafe pointer}} + // expected-note@-1{{reference to unsafe property 'pointer'}} + _ = unsafe pointer + } + } + + func otherTest(pointer: UnsafeMutablePointer?) { + if let pointer { // expected-warning{{expression uses unsafe constructs but is not marked with 'unsafe'}}{{19-19= = unsafe pointer}} + // expected-note@-1{{reference to parameter 'pointer' involves unsafe type 'UnsafeMutablePointer}} + _ = unsafe pointer + } + } +} diff --git a/test/expr/unary/async_await.swift b/test/expr/unary/async_await.swift index deb4a1cfed2ca..98bc9ba5ffe8d 100644 --- a/test/expr/unary/async_await.swift +++ b/test/expr/unary/async_await.swift @@ -232,7 +232,7 @@ func testAsyncExprWithoutAwait() async { if let result = result {} // expected-error {{expression is 'async' but is not marked with 'await'}} {{19-19=await }} // expected-warning@-1 {{value 'result' was defined but never used; consider replacing with boolean test}} // expected-note@-2 {{reference to async let 'result' is 'async'}} - if let result {} // expected-error {{expression is 'async' but is not marked with 'await'}} {{10-10=await }} + if let result {} // expected-error {{expression is 'async' but is not marked with 'await'}} {{16-16= = await result}} // expected-warning@-1 {{value 'result' was defined but never used; consider replacing with boolean test}} // expected-note@-2 {{reference to async let 'result' is 'async'}} let a = f("a") // expected-error {{expression is 'async' but is not marked with 'await'}} {{11-11=await }} From 87898710356598e98d6faad7fe7293a4c7873d34 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 27 Mar 2025 16:28:44 -0700 Subject: [PATCH 3/6] Diagnose @safe @unsafe when used together Fixes rdar://147943857. --- include/swift/AST/DiagnosticsSema.def | 5 ++++- lib/Sema/TypeCheckAttr.cpp | 10 +++++++++- test/Unsafe/safe.swift | 3 +++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 619d8d4ce78c4..22f32ab0c5ebd 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -8233,7 +8233,7 @@ NOTE(sending_function_result_with_sending_param_note, none, ()) //------------------------------------------------------------------------------ -// MARK: Strict Safety Diagnostics +// MARK: Strict Memory Safety Diagnostics //------------------------------------------------------------------------------ NOTE(note_reference_to_unsafe_decl,none, "%select{reference|call}0 to unsafe %kind1", @@ -8272,6 +8272,9 @@ NOTE(decl_storage_mark_safe,none, "add '@safe' if this type encapsulates the unsafe storage in " "a safe interface", ()) +ERROR(safe_and_unsafe_attr,none, + "%kindbase0 cannot be both @safe and @unsafe", (const Decl *)) + GROUPED_WARNING(unsafe_superclass,StrictMemorySafety,none, "%kindbase0 has superclass involving unsafe type %1", (const ValueDecl *, Type)) diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 1a6151c727c08..35e618e26b6a4 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -192,7 +192,6 @@ class AttributeChecker : public AttributeVisitor { IGNORED_ATTR(AllowFeatureSuppression) IGNORED_ATTR(PreInverseGenerics) IGNORED_ATTR(Safe) - IGNORED_ATTR(Unsafe) #undef IGNORED_ATTR void visitABIAttr(ABIAttr *attr) { @@ -445,6 +444,7 @@ class AttributeChecker : public AttributeVisitor { void visitLifetimeAttr(LifetimeAttr *attr); void visitAddressableSelfAttr(AddressableSelfAttr *attr); void visitAddressableForDependenciesAttr(AddressableForDependenciesAttr *attr); + void visitUnsafeAttr(UnsafeAttr *attr); }; } // end anonymous namespace @@ -8140,6 +8140,14 @@ AttributeChecker::visitAddressableForDependenciesAttr( } } +void AttributeChecker::visitUnsafeAttr(UnsafeAttr *attr) { + if (auto safeAttr = D->getAttrs().getAttribute()) { + D->diagnose(diag::safe_and_unsafe_attr, D) + .highlight(attr->getRange()) + .highlight(safeAttr->getRange()); + } +} + namespace { class ClosureAttributeChecker diff --git a/test/Unsafe/safe.swift b/test/Unsafe/safe.swift index af7823bb2a02e..04c9c637e6f7f 100644 --- a/test/Unsafe/safe.swift +++ b/test/Unsafe/safe.swift @@ -268,3 +268,6 @@ struct UnsafeWrapTest { } } } + +@safe @unsafe +struct ConfusedStruct { } // expected-error{{struct 'ConfusedStruct' cannot be both @safe and @unsafe}} From 8a8e108cae8237c65e13a0dc3052ab95b2c92001 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 27 Mar 2025 16:48:09 -0700 Subject: [PATCH 4/6] Stop propagating @unsafe/@safe from type definitions down to their members --- lib/AST/Decl.cpp | 13 +++++-------- test/Unsafe/safe.swift | 4 ++-- test/Unsafe/safe_argument_suppression.swift | 2 +- test/Unsafe/unsafe.swift | 4 ++-- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 61dc314cbeace..ab01653a6ed68 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1228,10 +1228,6 @@ ExplicitSafety Decl::getExplicitSafety() const { if (auto extSafety = getExplicitSafetyFromAttrs(ext)) return *extSafety; } - - if (auto enclosingNominal = enclosingDC->getSelfNominalTypeDecl()) - if (auto nominalSafety = getExplicitSafetyFromAttrs(enclosingNominal)) - return *nominalSafety; } // If an extension extends an unsafe nominal type, it's unsafe. @@ -1241,11 +1237,12 @@ ExplicitSafety Decl::getExplicitSafety() const { return ExplicitSafety::Unsafe; } - // If this is a pattern binding declaration, check whether the first - // variable is @unsafe. + // If this is a pattern binding declaration, check whether there is a + // safety-related attribute on the first variable we find. if (auto patternBinding = dyn_cast(this)) { - if (auto var = patternBinding->getSingleVar()) - return var->getExplicitSafety(); + for (auto index : range(patternBinding->getNumPatternEntries())) + if (auto var = patternBinding->getAnchoringVarDecl(index)) + return var->getExplicitSafety(); } return ExplicitSafety::Unspecified; diff --git a/test/Unsafe/safe.swift b/test/Unsafe/safe.swift index 04c9c637e6f7f..0e534203d12b7 100644 --- a/test/Unsafe/safe.swift +++ b/test/Unsafe/safe.swift @@ -252,11 +252,11 @@ func testUnsafeLHS() { @safe struct UnsafeWrapTest { - @unsafe var pointer: UnsafeMutablePointer? + var pointer: UnsafeMutablePointer? func test() { if let pointer { // expected-warning{{expression uses unsafe constructs but is not marked with 'unsafe'}}{{19-19= = unsafe pointer}} - // expected-note@-1{{reference to unsafe property 'pointer'}} + // expected-note@-1{{reference to property 'pointer' involves unsafe type 'UnsafeMutablePointer'}} _ = unsafe pointer } } diff --git a/test/Unsafe/safe_argument_suppression.swift b/test/Unsafe/safe_argument_suppression.swift index 4c60ad462265d..13d2f46f23715 100644 --- a/test/Unsafe/safe_argument_suppression.swift +++ b/test/Unsafe/safe_argument_suppression.swift @@ -38,7 +38,7 @@ class NotSafeSubclass: NotSafe { ns.stillUnsafe() // expected-warning{{expression uses unsafe constructs but is not marked with 'unsafe' [StrictMemorySafety]}} // expected-note@-1{{reference to parameter 'ns' involves unsafe type 'NotSafe'}} - // expected-note@-2{{reference to unsafe instance method 'stillUnsafe()'}} + // expected-note@-2{{reference to instance method 'stillUnsafe()' involves unsafe type 'NotSafe'}} } @safe func testImpliedSafetySubclass(ns: NotSafeSubclass) { diff --git a/test/Unsafe/unsafe.swift b/test/Unsafe/unsafe.swift index 0b4bbb809de04..ad5067e144997 100644 --- a/test/Unsafe/unsafe.swift +++ b/test/Unsafe/unsafe.swift @@ -49,7 +49,7 @@ extension ConformsToMultiP: MultiP { // expected-note@-1{{unsafe type 'UnsafeSuper' cannot satisfy safe associated type 'Ptr'}} @unsafe func f() -> UnsafeSuper { .init() // expected-warning{{expression uses unsafe constructs but is not marked with 'unsafe'}} - // expected-note@-1{{reference to unsafe initializer 'init()'}} + // expected-note@-1{{reference to initializer 'init()' involves unsafe type 'UnsafeSuper'}} } } @@ -156,7 +156,7 @@ func testMe( // expected-warning@+1{{expression uses unsafe constructs but is not marked with 'unsafe'}}{{7-7=unsafe }} _ = unsafeVar // expected-note{{reference to unsafe var 'unsafeVar'}} // expected-warning@+1{{expression uses unsafe constructs but is not marked with 'unsafe'}}{{3-3=unsafe }} - unsafeSuper.f() // expected-note{{reference to unsafe instance method 'f()'}} + unsafeSuper.f() // expected-note{{reference to instance method 'f()' involves unsafe type 'UnsafeSuper'}} // expected-note@-1{{reference to parameter 'unsafeSuper' involves unsafe type 'UnsafeSuper'}} // expected-warning@+1{{expression uses unsafe constructs but is not marked with 'unsafe'}}{{7-7=unsafe }} From b2f0ce44cc5323330c0432237d5955f13e1eaacf Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 27 Mar 2025 22:05:21 -0700 Subject: [PATCH 5/6] Remove a use of `@safe @unsafe` from the standard library --- stdlib/public/core/CTypes.swift | 3 +-- test/Macros/SwiftifyImport/CountedBy/SimpleSpan.swift | 4 +--- .../SwiftifyImport/CountedBy/SimpleSpanWithReturn.swift | 4 +--- .../Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift | 3 +-- test/Macros/SwiftifyImport/SizedBy/Opaque.swift | 2 +- test/Macros/SwiftifyImport/SizedBy/SimpleRawSpan.swift | 4 +--- .../SwiftifyImport/SizedBy/SimpleRawSpanWithReturn.swift | 4 +--- 7 files changed, 7 insertions(+), 17 deletions(-) diff --git a/stdlib/public/core/CTypes.swift b/stdlib/public/core/CTypes.swift index cee7b70a06ae4..20ecba2bcf9bb 100644 --- a/stdlib/public/core/CTypes.swift +++ b/stdlib/public/core/CTypes.swift @@ -157,8 +157,7 @@ public typealias CBool = Bool @frozen @unsafe public struct OpaquePointer { - @unsafe @usableFromInline - @safe + @usableFromInline internal var _rawValue: Builtin.RawPointer @usableFromInline @_transparent diff --git a/test/Macros/SwiftifyImport/CountedBy/SimpleSpan.swift b/test/Macros/SwiftifyImport/CountedBy/SimpleSpan.swift index 04fc023142a64..69de53f1d9cf6 100644 --- a/test/Macros/SwiftifyImport/CountedBy/SimpleSpan.swift +++ b/test/Macros/SwiftifyImport/CountedBy/SimpleSpan.swift @@ -1,9 +1,7 @@ // REQUIRES: swift_swift_parser // RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -dump-macro-expansions 2>&1 | %FileCheck --match-full-lines %s - -// rdar://145899513 ([StrictMemorySafety] Call to RawSpan::withUnsafeBytes not recognized as unsafe, while call to Span::withUnsafeBufferPointer is) -// RUN: not %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -strict-memory-safety -warnings-as-errors +// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -strict-memory-safety -warnings-as-errors @_SwiftifyImport(.countedBy(pointer: .param(1), count: "len"), .nonescaping(pointer: .param(1))) func myFunc(_ ptr: UnsafePointer, _ len: CInt) { diff --git a/test/Macros/SwiftifyImport/CountedBy/SimpleSpanWithReturn.swift b/test/Macros/SwiftifyImport/CountedBy/SimpleSpanWithReturn.swift index 215a4a94ecd55..28f60f4971371 100644 --- a/test/Macros/SwiftifyImport/CountedBy/SimpleSpanWithReturn.swift +++ b/test/Macros/SwiftifyImport/CountedBy/SimpleSpanWithReturn.swift @@ -1,9 +1,7 @@ // REQUIRES: swift_swift_parser // RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -dump-macro-expansions 2>&1 | %FileCheck --match-full-lines %s - -// rdar://145899513 ([StrictMemorySafety] Call to RawSpan::withUnsafeBytes not recognized as unsafe, while call to Span::withUnsafeBufferPointer is) -// RUN: not %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -strict-memory-safety -warnings-as-errors +// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -strict-memory-safety -warnings-as-errors @_SwiftifyImport(.countedBy(pointer: .param(1), count: "len"), .nonescaping(pointer: .param(1))) func myFunc(_ ptr: UnsafePointer, _ len: CInt) -> CInt { diff --git a/test/Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift b/test/Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift index 3d0818da1c029..b7774a244aa72 100644 --- a/test/Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift +++ b/test/Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift @@ -2,8 +2,7 @@ // RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -dump-macro-expansions 2>&1 | %FileCheck --match-full-lines %s -// rdar://145899513 ([StrictMemorySafety] Call to RawSpan::withUnsafeBytes not recognized as unsafe, while call to Span::withUnsafeBufferPointer is) -// RUN: not %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -strict-memory-safety -warnings-as-errors +// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -strict-memory-safety -warnings-as-errors @_SwiftifyImport(.countedBy(pointer: .param(1), count: "len1"), .countedBy(pointer: .param(3), count: "len2"), .nonescaping(pointer: .param(1))) func myFunc(_ ptr1: UnsafePointer, _ len1: CInt, _ ptr2: UnsafePointer, _ len2: CInt) { diff --git a/test/Macros/SwiftifyImport/SizedBy/Opaque.swift b/test/Macros/SwiftifyImport/SizedBy/Opaque.swift index 62eda98102627..b0377b80adb94 100644 --- a/test/Macros/SwiftifyImport/SizedBy/Opaque.swift +++ b/test/Macros/SwiftifyImport/SizedBy/Opaque.swift @@ -2,7 +2,7 @@ // RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -dump-macro-expansions -verify 2>&1 | %FileCheck --match-full-lines %s -// rdar://145899513 ([StrictMemorySafety] Call to RawSpan::withUnsafeBytes not recognized as unsafe, while call to Span::withUnsafeBufferPointer is) +// FIXME: Waiting for optional to handle nonescapable types // RUN: not %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -strict-memory-safety -warnings-as-errors @_SwiftifyImport(.sizedBy(pointer: .param(1), size: "size")) diff --git a/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpan.swift b/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpan.swift index 5c7fff0511685..c7ed798638e34 100644 --- a/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpan.swift +++ b/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpan.swift @@ -1,9 +1,7 @@ // REQUIRES: swift_swift_parser // RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -dump-macro-expansions 2>&1 | %FileCheck --match-full-lines %s - -// rdar://145899513 ([StrictMemorySafety] Call to RawSpan::withUnsafeBytes not recognized as unsafe, while call to Span::withUnsafeBufferPointer is) -// RUN: not %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -strict-memory-safety -warnings-as-errors +// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -strict-memory-safety -warnings-as-errors @_SwiftifyImport(.sizedBy(pointer: .param(1), size: "size"), .nonescaping(pointer: .param(1))) func myFunc(_ ptr: UnsafeRawPointer, _ size: CInt) { diff --git a/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpanWithReturn.swift b/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpanWithReturn.swift index 71a8f800f8d6c..92586787da5b1 100644 --- a/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpanWithReturn.swift +++ b/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpanWithReturn.swift @@ -1,9 +1,7 @@ // REQUIRES: swift_swift_parser // RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -dump-macro-expansions 2>&1 | %FileCheck --match-full-lines %s - -// rdar://145899513 ([StrictMemorySafety] Call to RawSpan::withUnsafeBytes not recognized as unsafe, while call to Span::withUnsafeBufferPointer is) -// RUN: not %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -strict-memory-safety -warnings-as-errors +// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -strict-memory-safety -warnings-as-errors @_SwiftifyImport(.sizedBy(pointer: .param(1), size: "size"), .nonescaping(pointer: .param(1))) func myFunc(_ ptr: UnsafeRawPointer, _ size: CInt) -> CInt { From a5df17ea3cecb624d26af3a4ab8cb3daf0978b84 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 27 Mar 2025 22:06:38 -0700 Subject: [PATCH 6/6] Suppress new `@safe @unsafe` error in Swift interfaces --- lib/Sema/TypeCheckAttr.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 35e618e26b6a4..dbfd21cd852f3 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -8144,7 +8144,8 @@ void AttributeChecker::visitUnsafeAttr(UnsafeAttr *attr) { if (auto safeAttr = D->getAttrs().getAttribute()) { D->diagnose(diag::safe_and_unsafe_attr, D) .highlight(attr->getRange()) - .highlight(safeAttr->getRange()); + .highlight(safeAttr->getRange()) + .warnInSwiftInterface(D->getDeclContext()); } }