Allow '@unsafe' on import declarations to silence '@preconcurrency' warning

'@preconcurrency' imports open up memory safety holes with respect to
Sendable, which are diagnosed under strict memory safety + strict
concurrency checking. Allow one to write '@unsafe' on those imports to
silence the diagnostic about it.
This commit is contained in:
Doug Gregor
2025-06-23 19:06:14 -07:00
parent c34f81e110
commit 0e3da0e499
5 changed files with 16 additions and 4 deletions

View File

@@ -834,7 +834,7 @@ SIMPLE_DECL_ATTR(sensitive, Sensitive,
159) 159)
SIMPLE_DECL_ATTR(unsafe, Unsafe, SIMPLE_DECL_ATTR(unsafe, Unsafe,
OnAbstractFunction | OnSubscript | OnVar | OnMacro | OnNominalType | OnExtension | OnTypeAlias | OnEnumElement, OnAbstractFunction | OnSubscript | OnVar | OnMacro | OnNominalType | OnExtension | OnTypeAlias | OnEnumElement | OnImport,
UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
160) 160)

View File

@@ -8481,7 +8481,7 @@ GROUPED_WARNING(override_safe_with_unsafe,StrictMemorySafety,none,
GROUPED_WARNING(preconcurrency_import_unsafe,StrictMemorySafety,none, GROUPED_WARNING(preconcurrency_import_unsafe,StrictMemorySafety,none,
"'@preconcurrency' import is not memory-safe because it can silently " "'@preconcurrency' import is not memory-safe because it can silently "
"introduce data races", ()) "introduce data races; add '@unsafe' to indicate that this is unsafe", ())
GROUPED_WARNING(unsafe_without_unsafe,StrictMemorySafety,none, GROUPED_WARNING(unsafe_without_unsafe,StrictMemorySafety,none,
"expression uses unsafe constructs but is not marked with 'unsafe'", ()) "expression uses unsafe constructs but is not marked with 'unsafe'", ())
GROUPED_WARNING(for_unsafe_without_unsafe,StrictMemorySafety,none, GROUPED_WARNING(for_unsafe_without_unsafe,StrictMemorySafety,none,

View File

@@ -2486,7 +2486,8 @@ public:
// concurrency checking enabled. // concurrency checking enabled.
if (ID->preconcurrency() && if (ID->preconcurrency() &&
Ctx.LangOpts.StrictConcurrencyLevel == StrictConcurrency::Complete && Ctx.LangOpts.StrictConcurrencyLevel == StrictConcurrency::Complete &&
Ctx.LangOpts.hasFeature(Feature::StrictMemorySafety)) { Ctx.LangOpts.hasFeature(Feature::StrictMemorySafety) &&
ID->getExplicitSafety() != ExplicitSafety::Unsafe) {
diagnoseUnsafeUse(UnsafeUse::forPreconcurrencyImport(ID)); diagnoseUnsafeUse(UnsafeUse::forPreconcurrencyImport(ID));
} }
} }

View File

@@ -195,7 +195,9 @@ void swift::diagnoseUnsafeUse(const UnsafeUse &use) {
case UnsafeUse::PreconcurrencyImport: { case UnsafeUse::PreconcurrencyImport: {
auto importDecl = cast<ImportDecl>(use.getDecl()); auto importDecl = cast<ImportDecl>(use.getDecl());
importDecl->diagnose(diag::preconcurrency_import_unsafe); importDecl->diagnose(diag::preconcurrency_import_unsafe)
.fixItInsert(importDecl->getAttributeInsertionLoc(false), "@unsafe ");
return; return;
} }
} }

View File

@@ -0,0 +1,9 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module-path %t/unsafe_swift_decls.swiftmodule %S/Inputs/unsafe_swift_decls.swift
// RUN: %target-typecheck-verify-swift -strict-memory-safety -enable-experimental-feature StrictConcurrency -I %t
// REQUIRES: concurrency
// REQUIRES: swift_feature_StrictConcurrency
@preconcurrency @unsafe import unsafe_swift_decls