Skip to content

Commit 326f0f4

Browse files
authored
Merge pull request #73212 from gottesmm/move-error
[region-isolation] Suppress non-Sendable region isolation errors appropriately when the type is imported by using @preconcurrency import.
2 parents a5d4904 + 9ce43d5 commit 326f0f4

7 files changed

+394
-17
lines changed

include/swift/Sema/Concurrency.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,18 @@
2323
namespace swift {
2424

2525
class SourceFile;
26+
class NominalTypeDecl;
2627

2728
/// If any of the imports in this source file was @preconcurrency but there were
2829
/// no diagnostics downgraded or suppressed due to that @preconcurrency, suggest
2930
/// that the attribute be removed.
3031
void diagnoseUnnecessaryPreconcurrencyImports(SourceFile &sf);
3132

33+
/// Determine whether the given nominal type has an explicit Sendable
34+
/// conformance (regardless of its availability).
35+
bool hasExplicitSendableConformance(NominalTypeDecl *nominal,
36+
bool applyModuleDefault = true);
37+
3238
} // namespace swift
3339

3440
#endif

lib/SILOptimizer/Mandatory/TransferNonSendable.cpp

Lines changed: 66 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include "swift/AST/ASTWalker.h"
1616
#include "swift/AST/DiagnosticsSIL.h"
1717
#include "swift/AST/Expr.h"
18+
#include "swift/AST/ProtocolConformance.h"
19+
#include "swift/AST/SourceFile.h"
1820
#include "swift/AST/Type.h"
1921
#include "swift/Basic/FrozenMultiMap.h"
2022
#include "swift/Basic/ImmutablePointerSet.h"
@@ -35,6 +37,7 @@
3537
#include "swift/SILOptimizer/PassManager/Transforms.h"
3638
#include "swift/SILOptimizer/Utils/PartitionUtils.h"
3739
#include "swift/SILOptimizer/Utils/VariableNameUtils.h"
40+
#include "swift/Sema/Concurrency.h"
3841
#include "llvm/ADT/DenseMap.h"
3942
#include "llvm/Support/Debug.h"
4043

@@ -55,6 +58,33 @@ using Region = PartitionPrimitives::Region;
5558
// MARK: Utilities
5659
//===----------------------------------------------------------------------===//
5760

61+
static std::optional<DiagnosticBehavior>
62+
getDiagnosticBehaviorLimitForValue(SILValue value) {
63+
auto *nom = value->getType().getNominalOrBoundGenericNominal();
64+
if (!nom)
65+
return {};
66+
67+
auto declRef = value->getFunction()->getDeclRef();
68+
if (!declRef)
69+
return {};
70+
71+
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;
86+
}
87+
5888
static Expr *inferArgumentExprFromApplyExpr(ApplyExpr *sourceApply,
5989
FullApplySite fai,
6090
const Operand *op) {
@@ -438,14 +468,19 @@ class UseAfterTransferDiagnosticEmitter {
438468
emitUnknownPatternError();
439469
}
440470

471+
std::optional<DiagnosticBehavior> getBehaviorLimit() const {
472+
return getDiagnosticBehaviorLimitForValue(transferOp->get());
473+
}
474+
441475
void
442476
emitNamedIsolationCrossingError(SILLocation loc, Identifier name,
443477
SILIsolationInfo namedValuesIsolationInfo,
444478
ApplyIsolationCrossing isolationCrossing) {
445479
// Emit the short error.
446480
diagnoseError(loc, diag::regionbasedisolation_named_transfer_yields_race,
447481
name)
448-
.highlight(loc.getSourceRange());
482+
.highlight(loc.getSourceRange())
483+
.limitBehaviorIf(getBehaviorLimit());
449484

450485
// Then emit the note with greater context.
451486
SmallString<64> descriptiveKindStr;
@@ -466,7 +501,8 @@ class UseAfterTransferDiagnosticEmitter {
466501
loc, diag::regionbasedisolation_transfer_yields_race_with_isolation,
467502
inferredType, isolationCrossing.getCallerIsolation(),
468503
isolationCrossing.getCalleeIsolation())
469-
.highlight(loc.getSourceRange());
504+
.highlight(loc.getSourceRange())
505+
.limitBehaviorIf(getBehaviorLimit());
470506
emitRequireInstDiagnostics();
471507
}
472508

@@ -475,7 +511,8 @@ class UseAfterTransferDiagnosticEmitter {
475511
// Emit the short error.
476512
diagnoseError(loc, diag::regionbasedisolation_named_transfer_yields_race,
477513
name)
478-
.highlight(loc.getSourceRange());
514+
.highlight(loc.getSourceRange())
515+
.limitBehaviorIf(getBehaviorLimit());
479516

480517
// Then emit the note with greater context.
481518
diagnoseNote(
@@ -493,7 +530,8 @@ class UseAfterTransferDiagnosticEmitter {
493530
diag::
494531
regionbasedisolation_transfer_yields_race_stronglytransferred_binding,
495532
inferredType)
496-
.highlight(loc.getSourceRange());
533+
.highlight(loc.getSourceRange())
534+
.limitBehaviorIf(getBehaviorLimit());
497535
emitRequireInstDiagnostics();
498536
}
499537

@@ -502,7 +540,8 @@ class UseAfterTransferDiagnosticEmitter {
502540
diagnoseError(loc,
503541
diag::regionbasedisolation_transfer_yields_race_no_isolation,
504542
inferredType)
505-
.highlight(loc.getSourceRange());
543+
.highlight(loc.getSourceRange())
544+
.limitBehaviorIf(getBehaviorLimit());
506545
emitRequireInstDiagnostics();
507546
}
508547

@@ -513,7 +552,8 @@ class UseAfterTransferDiagnosticEmitter {
513552
// Emit the short error.
514553
diagnoseError(loc, diag::regionbasedisolation_named_transfer_yields_race,
515554
name)
516-
.highlight(loc.getSourceRange());
555+
.highlight(loc.getSourceRange())
556+
.limitBehaviorIf(getBehaviorLimit());
517557

518558
SmallString<64> descriptiveKindStr;
519559
{
@@ -535,13 +575,15 @@ class UseAfterTransferDiagnosticEmitter {
535575
diagnoseError(loc, diag::regionbasedisolation_isolated_capture_yields_race,
536576
inferredType, isolationCrossing.getCalleeIsolation(),
537577
isolationCrossing.getCallerIsolation())
538-
.highlight(loc.getSourceRange());
578+
.highlight(loc.getSourceRange())
579+
.limitBehaviorIf(getBehaviorLimit());
539580
emitRequireInstDiagnostics();
540581
}
541582

542583
void emitUnknownPatternError() {
543584
diagnoseError(transferOp->getUser(),
544-
diag::regionbasedisolation_unknown_pattern);
585+
diag::regionbasedisolation_unknown_pattern)
586+
.limitBehaviorIf(getBehaviorLimit());
545587
}
546588

547589
private:
@@ -941,20 +983,26 @@ class TransferNonTransferrableDiagnosticEmitter {
941983
return info.nonTransferrable.dyn_cast<SILInstruction *>();
942984
}
943985

986+
std::optional<DiagnosticBehavior> getBehaviorLimit() const {
987+
return getDiagnosticBehaviorLimitForValue(info.transferredOperand->get());
988+
}
989+
944990
/// Return the isolation region info for \p getNonTransferrableValue().
945991
SILIsolationInfo getIsolationRegionInfo() const {
946992
return info.isolationRegionInfo;
947993
}
948994

949995
void emitUnknownPatternError() {
950996
diagnoseError(getOperand()->getUser(),
951-
diag::regionbasedisolation_unknown_pattern);
997+
diag::regionbasedisolation_unknown_pattern)
998+
.limitBehaviorIf(getBehaviorLimit());
952999
}
9531000

9541001
void emitUnknownUse(SILLocation loc) {
9551002
// TODO: This will eventually be an unknown pattern error.
956-
diagnoseError(
957-
loc, diag::regionbasedisolation_task_or_actor_isolated_transferred);
1003+
diagnoseError(loc,
1004+
diag::regionbasedisolation_task_or_actor_isolated_transferred)
1005+
.limitBehaviorIf(getBehaviorLimit());
9581006
}
9591007

9601008
void emitFunctionArgumentApply(SILLocation loc, Type type,
@@ -967,7 +1015,8 @@ class TransferNonTransferrableDiagnosticEmitter {
9671015
diagnoseError(loc, diag::regionbasedisolation_arg_transferred,
9681016
StringRef(descriptiveKindStr), type,
9691017
crossing.getCalleeIsolation())
970-
.highlight(getOperand()->getUser()->getLoc().getSourceRange());
1018+
.highlight(getOperand()->getUser()->getLoc().getSourceRange())
1019+
.limitBehaviorIf(getBehaviorLimit());
9711020
}
9721021

9731022
void emitNamedFunctionArgumentClosure(SILLocation loc, Identifier name,
@@ -995,13 +1044,15 @@ class TransferNonTransferrableDiagnosticEmitter {
9951044
auto diag =
9961045
diag::regionbasedisolation_arg_passed_to_strongly_transferred_param;
9971046
diagnoseError(loc, diag, descriptiveKindStr, type)
998-
.highlight(getOperand()->getUser()->getLoc().getSourceRange());
1047+
.highlight(getOperand()->getUser()->getLoc().getSourceRange())
1048+
.limitBehaviorIf(getBehaviorLimit());
9991049
}
10001050

10011051
void emitNamedOnlyError(SILLocation loc, Identifier name) {
10021052
diagnoseError(loc, diag::regionbasedisolation_named_transfer_yields_race,
10031053
name)
1004-
.highlight(getOperand()->getUser()->getLoc().getSourceRange());
1054+
.highlight(getOperand()->getUser()->getLoc().getSourceRange())
1055+
.limitBehaviorIf(getBehaviorLimit());
10051056
}
10061057

10071058
void emitNamedIsolation(SILLocation loc, Identifier name,
@@ -1176,7 +1227,7 @@ bool TransferNonTransferrableDiagnosticInferrer::run() {
11761227
if (!isolation) {
11771228
// Otherwise, emit a "we don't know error" that tells the user to file a
11781229
// bug.
1179-
diagnoseError(op->getUser(), diag::regionbasedisolation_unknown_pattern);
1230+
diagnosticEmitter.emitUnknownPatternError();
11801231
return false;
11811232
}
11821233
assert(isolation && "Expected non-null");

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,8 +789,8 @@ SendableCheckContext::implicitSendableDiagnosticBehavior() const {
789789

790790
/// Determine whether the given nominal type has an explicit Sendable
791791
/// conformance (regardless of its availability).
792-
static bool hasExplicitSendableConformance(NominalTypeDecl *nominal,
793-
bool applyModuleDefault = true) {
792+
bool swift::hasExplicitSendableConformance(NominalTypeDecl *nominal,
793+
bool applyModuleDefault) {
794794
ASTContext &ctx = nominal->getASTContext();
795795
auto nominalModule = nominal->getParentModule();
796796

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
public class NonSendableKlass {
3+
public init() {}
4+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
public class NonSendableKlass {
3+
public init() {}
4+
}
5+
6+
public class ExplicitlyNonSendableKlass {
7+
public init() {}
8+
}
9+
10+
@available(*, unavailable)
11+
extension ExplicitlyNonSendableKlass: Sendable {}

0 commit comments

Comments
 (0)