Skip to content

Commit e4dac75

Browse files
committed
Unify two implementations of "concurrency diagnostic behavior limit"
The "send non-Sendable" pass had a copy of the code for determining what limit to put on the diagnostic behavior for a given reference to a nominal type declaration. Rather than update that copy for the recent changes to the canonical version of this in the type checker, share the computation.
1 parent 0f8c478 commit e4dac75

File tree

3 files changed

+46
-43
lines changed

3 files changed

+46
-43
lines changed

include/swift/Sema/Concurrency.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,17 @@
2020
#ifndef SWIFT_SEMA_CONCURRENCY_H
2121
#define SWIFT_SEMA_CONCURRENCY_H
2222

23+
#include <optional>
24+
2325
namespace swift {
2426

2527
class DeclContext;
2628
class SourceFile;
2729
class NominalTypeDecl;
2830
class VarDecl;
2931

32+
enum class DiagnosticBehavior: uint8_t;
33+
3034
/// If any of the imports in this source file was @preconcurrency but there were
3135
/// no diagnostics downgraded or suppressed due to that @preconcurrency, suggest
3236
/// that the attribute be removed.
@@ -44,6 +48,12 @@ bool hasExplicitSendableConformance(NominalTypeDecl *nominal,
4448
bool diagnoseNonSendableFromDeinit(
4549
SourceLoc refLoc, VarDecl *var, DeclContext *dc);
4650

51+
/// Determinate the appropriate diagnostic behavior when referencing
52+
/// the given nominal type from the given declaration context.
53+
std::optional<DiagnosticBehavior>
54+
getConcurrencyDiagnosticBehaviorLimit(NominalTypeDecl *nominal,
55+
const DeclContext *fromDC);
56+
4757
} // namespace swift
4858

4959
#endif

lib/SILOptimizer/Mandatory/TransferNonSendable.cpp

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,20 +69,7 @@ getDiagnosticBehaviorLimitForValue(SILValue value) {
6969
return {};
7070

7171
auto *fromDC = declRef.getInnermostDeclContext();
72-
auto attributedImport = nom->findImport(fromDC);
73-
if (!attributedImport ||
74-
!attributedImport->options.contains(ImportFlags::Preconcurrency))
75-
return {};
76-
77-
if (auto *sourceFile = fromDC->getParentSourceFile())
78-
sourceFile->setImportUsedPreconcurrency(*attributedImport);
79-
80-
if (hasExplicitSendableConformance(nom))
81-
return DiagnosticBehavior::Warning;
82-
83-
return attributedImport->module.importedModule->isConcurrencyChecked()
84-
? DiagnosticBehavior::Warning
85-
: DiagnosticBehavior::Ignore;
72+
return getConcurrencyDiagnosticBehaviorLimit(nom, fromDC);
8673
}
8774

8875
static std::optional<SILDeclRef> getDeclRefForCallee(SILInstruction *inst) {

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -835,41 +835,47 @@ DiagnosticBehavior SendableCheckContext::diagnosticBehavior(
835835
}
836836

837837
std::optional<DiagnosticBehavior>
838-
SendableCheckContext::preconcurrencyBehavior(Decl *decl) const {
839-
if (!decl)
840-
return std::nullopt;
838+
swift::getConcurrencyDiagnosticBehaviorLimit(NominalTypeDecl *nominal,
839+
const DeclContext *fromDC) {
840+
ModuleDecl *importedModule = nullptr;
841+
if (nominal->getAttrs().hasAttribute<PreconcurrencyAttr>()) {
842+
// If the declaration itself has the @preconcurrency attribute,
843+
// respect it.
844+
importedModule = nominal->getParentModule();
845+
} else {
846+
// Determine whether this nominal type is visible via a @preconcurrency
847+
// import.
848+
auto import = nominal->findImport(fromDC);
849+
auto sourceFile = fromDC->getParentSourceFile();
841850

842-
if (auto *nominal = dyn_cast<NominalTypeDecl>(decl)) {
843-
ModuleDecl *importedModule = nullptr;
844-
if (nominal->getAttrs().hasAttribute<PreconcurrencyAttr>()) {
845-
// If the declaration itself has the @preconcurrency attribute,
846-
// respect it.
847-
importedModule = nominal->getParentModule();
848-
} else {
849-
// Determine whether this nominal type is visible via a @preconcurrency
850-
// import.
851-
auto import = nominal->findImport(fromDC);
852-
auto sourceFile = fromDC->getParentSourceFile();
851+
if (!import || !import->options.contains(ImportFlags::Preconcurrency))
852+
return std::nullopt;
853853

854-
if (!import || !import->options.contains(ImportFlags::Preconcurrency))
855-
return std::nullopt;
854+
if (sourceFile)
855+
sourceFile->setImportUsedPreconcurrency(*import);
856856

857-
if (sourceFile)
858-
sourceFile->setImportUsedPreconcurrency(*import);
857+
importedModule = import->module.importedModule;
858+
}
859859

860-
importedModule = import->module.importedModule;
861-
}
860+
// When the type is explicitly non-Sendable, @preconcurrency imports
861+
// downgrade the diagnostic to a warning in Swift 6.
862+
if (hasExplicitSendableConformance(nominal))
863+
return DiagnosticBehavior::Warning;
862864

863-
// When the type is explicitly non-Sendable, @preconcurrency imports
864-
// downgrade the diagnostic to a warning in Swift 6.
865-
if (hasExplicitSendableConformance(nominal))
866-
return DiagnosticBehavior::Warning;
865+
// When the type is implicitly non-Sendable, `@preconcurrency` suppresses
866+
// diagnostics until the imported module enables Swift 6.
867+
return importedModule->isConcurrencyChecked()
868+
? DiagnosticBehavior::Warning
869+
: DiagnosticBehavior::Ignore;
870+
}
871+
872+
std::optional<DiagnosticBehavior>
873+
SendableCheckContext::preconcurrencyBehavior(Decl *decl) const {
874+
if (!decl)
875+
return std::nullopt;
867876

868-
// When the type is implicitly non-Sendable, `@preconcurrency` suppresses
869-
// diagnostics until the imported module enables Swift 6.
870-
return importedModule->isConcurrencyChecked()
871-
? DiagnosticBehavior::Warning
872-
: DiagnosticBehavior::Ignore;
877+
if (auto *nominal = dyn_cast<NominalTypeDecl>(decl)) {
878+
return getConcurrencyDiagnosticBehaviorLimit(nominal, fromDC);
873879
}
874880

875881
return std::nullopt;

0 commit comments

Comments
 (0)