Skip to content

Commit 813f1dc

Browse files
authored
Merge pull request #80384 from DougGregor/isolated-conformances-checkedcast-enable
Prohibit isolated conformances for checked casts to potentially-SendableMetatype types
2 parents 68b95f8 + c08bd56 commit 813f1dc

11 files changed

+83
-39
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8470,9 +8470,6 @@ NOTE(note_isolate_conformance_to_global_actor,none,
84708470
NOTE(note_depends_on_isolated_conformance,none,
84718471
"conformance depends on %0 conformance of %1 to %kind2",
84728472
(ActorIsolation, Type, const ValueDecl *))
8473-
ERROR(nonisolated_conformance_depends_on_isolated_conformance,none,
8474-
"conformance of %0 to %1 depends on %2 conformance of %3 to %4; mark it as '%5'",
8475-
(Type, DeclName, ActorIsolation, Type, DeclName, StringRef))
84768473
ERROR(isolated_conformance_with_sendable,none,
84778474
"%4 conformance of %0 to %1 cannot satisfy conformance "
84788475
"requirement for a %select{`Sendable`|`SendableMetatype`}2 type "

include/swift/Basic/Features.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -488,9 +488,6 @@ ADOPTABLE_EXPERIMENTAL_FEATURE(AsyncCallerExecution, false)
488488
/// Allow custom availability domains to be defined and referenced.
489489
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(CustomAvailability, true)
490490

491-
/// Be strict about the Sendable conformance of metatypes.
492-
EXPERIMENTAL_FEATURE(StrictSendableMetatypes, true)
493-
494491
/// Allow public enumerations to be extensible by default
495492
/// regardless of whether the module they are declared in
496493
/// is resilient or not.

lib/AST/ConformanceLookup.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,10 +387,10 @@ static ProtocolConformanceRef getBuiltinMetaTypeTypeConformance(
387387
if (auto kp = protocol->getKnownProtocolKind()) {
388388
switch (*kp) {
389389
case KnownProtocolKind::Sendable:
390-
// Metatypes are generally Sendable, but under StrictSendableMetatypes we
390+
// Metatypes are generally Sendable, but with isolated conformances we
391391
// cannot assume that metatypes based on type parameters are Sendable.
392392
// Therefore, check for conformance to SendableMetatype.
393-
if (ctx.LangOpts.hasFeature(Feature::StrictSendableMetatypes)) {
393+
if (ctx.LangOpts.hasFeature(Feature::IsolatedConformances)) {
394394
auto sendableMetatypeProto =
395395
ctx.getProtocol(KnownProtocolKind::SendableMetatype);
396396
if (sendableMetatypeProto) {

lib/AST/FeatureSet.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,6 @@ UNINTERESTING_FEATURE(NonfrozenEnumExhaustivity)
276276
UNINTERESTING_FEATURE(ClosureIsolation)
277277
UNINTERESTING_FEATURE(Extern)
278278
UNINTERESTING_FEATURE(ConsumeSelfInDeinit)
279-
UNINTERESTING_FEATURE(StrictSendableMetatypes)
280279

281280
static bool usesFeatureBitwiseCopyable2(Decl *decl) {
282281
if (!decl->getModuleContext()->isStdlibModule()) {

lib/SILGen/SILGenDynamicCast.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -308,16 +308,17 @@ namespace {
308308
if (!TargetType->isAnyExistentialType())
309309
return CastingIsolatedConformances::Allow;
310310

311-
// Only do this if isolated conformances are enabled.
311+
// If there is a conformance to SendableMetatype, then this existential
312+
// can leave the current isolation domain. Prohibit isolated conformances.
312313
ASTContext &ctx = TargetType->getASTContext();
313-
if (!ctx.LangOpts.hasFeature(Feature::IsolatedConformances))
314-
return CastingIsolatedConformances::Allow;
314+
Type checkType;
315+
if (auto existentialMetatype = TargetType->getAs<ExistentialMetatypeType>())
316+
checkType = existentialMetatype->getInstanceType();
317+
else
318+
checkType = TargetType;
315319

316320
auto proto = ctx.getProtocol(KnownProtocolKind::SendableMetatype);
317-
318-
// If there is a conformance to SendableMetatype, then this existential
319-
// can leave the current isolation domain. Prohibit isolated conformances.
320-
if (proto && lookupConformance(TargetType, proto, /*allowMissing=*/false))
321+
if (proto && lookupConformance(checkType, proto, /*allowMissing=*/false))
321322
return CastingIsolatedConformances::Prohibit;
322323

323324
return CastingIsolatedConformances::Allow;

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3011,7 +3011,7 @@ namespace {
30113011
// FIXME: When passing to a sending parameter, should this be handled
30123012
// by region isolation? Or should it always be handled by region
30133013
// isolation?
3014-
if (ctx.LangOpts.hasFeature(Feature::StrictSendableMetatypes) &&
3014+
if (ctx.LangOpts.hasFeature(Feature::IsolatedConformances) &&
30153015
(mayExecuteConcurrentlyWith(
30163016
localFunc.getAsDeclContext(), getDeclContext()) ||
30173017
(explicitClosure && explicitClosure->isPassedToSendingParameter()))) {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: %target-swift-frontend -typecheck -verify -target %target-swift-5.1-abi-triple -swift-version 6 -enable-experimental-feature IsolatedConformances -enable-experimental-feature InferIsolatedConformances %s
2+
3+
// REQUIRES: swift_feature_IsolatedConformances
4+
// REQUIRES: swift_feature_InferIsolatedConformances
5+
// REQUIRES: concurrency
6+
7+
protocol P {
8+
func f()
9+
}
10+
11+
@SomeGlobalActor
12+
protocol Q {
13+
func g()
14+
}
15+
16+
@globalActor
17+
actor SomeGlobalActor {
18+
static let shared = SomeGlobalActor()
19+
}
20+
21+
@SomeGlobalActor
22+
protocol R {
23+
func h()
24+
}
25+
26+
@SomeGlobalActor
27+
class CExplicit: P {
28+
func f() { } // okay! conformance above is isolated
29+
}
30+
31+
// If the protocol itself is isolated, don't do anything.
32+
extension CExplicit: Q {
33+
func g() { }
34+
}
35+
36+
// expected-error@+3{{conformance of 'CNonIsolated' to protocol 'P' crosses into global actor 'SomeGlobalActor'-isolated code and can cause data races}}
37+
// expected-note@+2{{turn data races into runtime errors with '@preconcurrency'}}
38+
// expected-note@+1{{isolate this conformance to the global actor 'SomeGlobalActor' with '@SomeGlobalActor'}}{{33-33=@SomeGlobalActor }}
39+
nonisolated class CNonIsolated: P {
40+
@SomeGlobalActor func f() { } // expected-note{{global actor 'SomeGlobalActor'-isolated instance method 'f()' cannot satisfy nonisolated requirement}}
41+
}
42+
43+
func acceptSendablePMeta<T: Sendable & P>(_: T.Type) { }
44+
func acceptSendableQMeta<T: Sendable & Q>(_: T.Type) { }
45+
46+
nonisolated func testConformancesFromNonisolated() {
47+
let _: any P = CExplicit() // expected-error{{global actor 'SomeGlobalActor'-isolated conformance of 'CExplicit' to 'P' cannot be used in nonisolated context}}
48+
49+
let _: any P = CNonIsolated()
50+
51+
// Okay, these are nonisolated conformances.
52+
let _: any Q = CExplicit()
53+
}

test/Concurrency/isolated_conformance_sil.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
// RUN: %target-swift-frontend -target %target-swift-5.1-abi-triple -Xllvm -sil-print-types -emit-silgen -enable-experimental-feature IsolatedConformances -verify %s | %FileCheck %s
2-
3-
// REQUIRES: swift_feature_IsolatedConformances
4-
// REQUIRES: concurrency
1+
// RUN: %target-swift-frontend -target %target-swift-5.1-abi-triple -Xllvm -sil-print-types -emit-silgen -verify %s | %FileCheck %s
52

63
protocol P { }
74

test/Concurrency/sendable_metatype.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
// RUN: %target-typecheck-verify-swift -swift-version 6 -enable-experimental-feature StrictSendableMetatypes -emit-sil -o /dev/null
1+
// RUN: %target-typecheck-verify-swift -swift-version 6 -enable-experimental-feature IsolatedConformances -emit-sil -o /dev/null
22

33
// REQUIRES: concurrency
4-
// REQUIRES: swift_feature_StrictSendableMetatypes
4+
// REQUIRES: swift_feature_IsolatedConformances
55

66

77
protocol Q {

test/Concurrency/sendable_metatype_typecheck.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
// RUN: %target-typecheck-verify-swift -swift-version 6 -enable-experimental-feature StrictSendableMetatypes
1+
// RUN: %target-typecheck-verify-swift -swift-version 6 -enable-experimental-feature IsolatedConformances
22

33
// REQUIRES: concurrency
4-
// REQUIRES: swift_feature_StrictSendableMetatypes
4+
// REQUIRES: swift_feature_IsolatedConformances
55

66
// This test checks for typecheck-only diagnostics involving non-sendable
77
// metatypes.

test/SILGen/subclass_existentials.swift

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -296,17 +296,17 @@ func downcasts(
296296
let _ = baseAndP as! Derived
297297

298298
// CHECK: [[COPIED:%.*]] = copy_value [[ARG0]] : $any Base<Int> & P
299-
// CHECK-NEXT: checked_cast_br any Base<Int> & P in [[COPIED]] : $any Base<Int> & P to any Derived & R
299+
// CHECK-NEXT: checked_cast_br [prohibit_isolated_conformances] any Base<Int> & P in [[COPIED]] : $any Base<Int> & P to any Derived & R
300300
let _ = baseAndP as? (Derived & R)
301301

302302
// CHECK: [[COPIED:%.*]] = copy_value [[ARG0]] : $any Base<Int> & P
303-
// CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $any Base<Int> & P to any Derived & R
303+
// CHECK-NEXT: unconditional_checked_cast [prohibit_isolated_conformances] [[COPIED]] : $any Base<Int> & P to any Derived & R
304304
let _ = baseAndP as! (Derived & R)
305305

306-
// CHECK: checked_cast_br Derived.Type in %3 : $@thick Derived.Type to any (Derived & R).Type
306+
// CHECK: checked_cast_br [prohibit_isolated_conformances] Derived.Type in %3 : $@thick Derived.Type to any (Derived & R).Type
307307
let _ = derivedType as? (Derived & R).Type
308308

309-
// CHECK: unconditional_checked_cast %3 : $@thick Derived.Type to any (Derived & R).Type
309+
// CHECK: unconditional_checked_cast [prohibit_isolated_conformances] %3 : $@thick Derived.Type to any (Derived & R).Type
310310
let _ = derivedType as! (Derived & R).Type
311311

312312
// CHECK: checked_cast_br any (Base<Int> & P).Type in %2 : $@thick any (Base<Int> & P).Type to Derived.Type
@@ -315,10 +315,10 @@ func downcasts(
315315
// CHECK: unconditional_checked_cast %2 : $@thick any (Base<Int> & P).Type to Derived.Type
316316
let _ = baseAndPType as! Derived.Type
317317

318-
// CHECK: checked_cast_br any (Base<Int> & P).Type in %2 : $@thick any (Base<Int> & P).Type to any (Derived & R).Type
318+
// CHECK: checked_cast_br [prohibit_isolated_conformances] any (Base<Int> & P).Type in %2 : $@thick any (Base<Int> & P).Type to any (Derived & R).Type
319319
let _ = baseAndPType as? (Derived & R).Type
320320

321-
// CHECK: unconditional_checked_cast %2 : $@thick any (Base<Int> & P).Type to any (Derived & R).Type
321+
// CHECK: unconditional_checked_cast [prohibit_isolated_conformances] %2 : $@thick any (Base<Int> & P).Type to any (Derived & R).Type
322322
let _ = baseAndPType as! (Derived & R).Type
323323

324324
// CHECK: return
@@ -378,33 +378,33 @@ func archetypeDowncasts<S,
378378
// CHECK: [[COPY:%.*]] = alloc_stack $S
379379
// CHECK-NEXT: copy_addr %0 to [init] [[COPY]] : $*S
380380
// CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $any Base<T> & P
381-
// CHECK-NEXT: checked_cast_addr_br take_always S in [[COPY]] : $*S to any Base<T> & P in [[RESULT]] : $*any Base<T> & P
381+
// CHECK-NEXT: checked_cast_addr_br [prohibit_isolated_conformances] take_always S in [[COPY]] : $*S to any Base<T> & P in [[RESULT]] : $*any Base<T> & P
382382
let _ = s as? (Base<T> & P)
383383

384384
// CHECK: [[COPY:%.*]] = alloc_stack $S
385385
// CHECK-NEXT: copy_addr [[ARG0]] to [init] [[COPY]] : $*S
386386
// CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $any Base<T> & P
387-
// CHECK-NEXT: unconditional_checked_cast_addr S in [[COPY]] : $*S to any Base<T> & P in [[RESULT]] : $*any Base<T> & P
387+
// CHECK-NEXT: unconditional_checked_cast_addr [prohibit_isolated_conformances] S in [[COPY]] : $*S to any Base<T> & P in [[RESULT]] : $*any Base<T> & P
388388
let _ = s as! (Base<T> & P)
389389

390390
// CHECK: [[COPY:%.*]] = alloc_stack $S
391391
// CHECK-NEXT: copy_addr [[ARG0]] to [init] [[COPY]] : $*S
392392
// CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $any Base<Int> & P
393-
// CHECK-NEXT: checked_cast_addr_br take_always S in [[COPY]] : $*S to any Base<Int> & P in [[RESULT]] : $*any Base<Int> & P
393+
// CHECK-NEXT: checked_cast_addr_br [prohibit_isolated_conformances] take_always S in [[COPY]] : $*S to any Base<Int> & P in [[RESULT]] : $*any Base<Int> & P
394394
let _ = s as? (Base<Int> & P)
395395

396396
// CHECK: [[COPY:%.*]] = alloc_stack $S
397397
// CHECK-NEXT: copy_addr [[ARG0]] to [init] [[COPY]] : $*S
398398
// CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $any Base<Int> & P
399-
// CHECK-NEXT: unconditional_checked_cast_addr S in [[COPY]] : $*S to any Base<Int> & P in [[RESULT]] : $*any Base<Int> & P
399+
// CHECK-NEXT: unconditional_checked_cast_addr [prohibit_isolated_conformances] S in [[COPY]] : $*S to any Base<Int> & P in [[RESULT]] : $*any Base<Int> & P
400400
let _ = s as! (Base<Int> & P)
401401

402402
// CHECK: [[COPIED:%.*]] = copy_value [[ARG5]] : $BaseTAndP
403-
// CHECK-NEXT: checked_cast_br BaseTAndP in [[COPIED]] : $BaseTAndP to any Derived & R
403+
// CHECK-NEXT: checked_cast_br [prohibit_isolated_conformances] BaseTAndP in [[COPIED]] : $BaseTAndP to any Derived & R
404404
let _ = baseTAndP_archetype as? (Derived & R)
405405

406406
// CHECK: [[COPIED:%.*]] = copy_value [[ARG5]] : $BaseTAndP
407-
// CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $BaseTAndP to any Derived & R
407+
// CHECK-NEXT: unconditional_checked_cast [prohibit_isolated_conformances] [[COPIED]] : $BaseTAndP to any Derived & R
408408
let _ = baseTAndP_archetype as! (Derived & R)
409409

410410
// CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $any Base<T> & P
@@ -447,11 +447,11 @@ func archetypeDowncasts<S,
447447
let _ = baseTAndP_concrete as! BaseTAndP
448448

449449
// CHECK: [[COPIED:%.*]] = copy_value [[ARG6]] : $BaseIntAndP
450-
// CHECK-NEXT: checked_cast_br BaseIntAndP in [[COPIED]] : $BaseIntAndP to any Derived & R
450+
// CHECK-NEXT: checked_cast_br [prohibit_isolated_conformances] BaseIntAndP in [[COPIED]] : $BaseIntAndP to any Derived & R
451451
let _ = baseIntAndP_archetype as? (Derived & R)
452452

453453
// CHECK: [[COPIED:%.*]] = copy_value [[ARG6]] : $BaseIntAndP
454-
// CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $BaseIntAndP to any Derived & R
454+
// CHECK-NEXT: unconditional_checked_cast [prohibit_isolated_conformances] [[COPIED]] : $BaseIntAndP to any Derived & R
455455
let _ = baseIntAndP_archetype as! (Derived & R)
456456

457457
// CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $any Base<Int> & P

0 commit comments

Comments
 (0)