Skip to content

Commit 5889371

Browse files
committed
TypeCheckType: Do not emit migration mode diags if nonisolated(nonsending) is explicit
This broke when we split `@execution(...)` into `@concurrent` and `nonisolated(nonsending)` because the latter became its own `TypeRepr`, whereas the condition for whether to attempt migration diagnostics inside `resolveASTFunctionType` is still based on the function type's attributes alone. (cherry picked from commit bee2b67)
1 parent 9ccb828 commit 5889371

File tree

2 files changed

+86
-32
lines changed

2 files changed

+86
-32
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2418,6 +2418,11 @@ namespace {
24182418
class TypeAttrSet {
24192419
const ASTContext &ctx;
24202420

2421+
/// FIXME:
2422+
/// `nonisolated(nonsending)` is modeled as a separate `TypeRepr`, but
2423+
/// needs to be considered together with subsequent attributes.
2424+
CallerIsolatedTypeRepr *nonisolatedNonsendingAttr;
2425+
24212426
llvm::TinyPtrVector<CustomAttr*> customAttrs;
24222427
EnumMap<TypeAttrKind, TypeAttribute *> typeAttrs;
24232428

@@ -2429,7 +2434,9 @@ namespace {
24292434
#endif
24302435

24312436
public:
2432-
TypeAttrSet(const ASTContext &ctx) : ctx(ctx) {}
2437+
TypeAttrSet(const ASTContext &ctx,
2438+
CallerIsolatedTypeRepr *nonisolatedNonsendingAttr = nullptr)
2439+
: ctx(ctx), nonisolatedNonsendingAttr(nonisolatedNonsendingAttr) {}
24332440

24342441
TypeAttrSet(const TypeAttrSet &) = delete;
24352442
TypeAttrSet &operator=(const TypeAttrSet &) = delete;
@@ -2448,6 +2455,10 @@ namespace {
24482455
/// will be diagnosed.
24492456
void accumulate(ArrayRef<TypeOrCustomAttr> attrs);
24502457

2458+
CallerIsolatedTypeRepr *getNonisolatedNonsendingAttr() const {
2459+
return nonisolatedNonsendingAttr;
2460+
}
2461+
24512462
/// Return all of the custom attributes.
24522463
ArrayRef<CustomAttr*> getCustomAttrs() const {
24532464
return customAttrs;
@@ -2547,9 +2558,17 @@ namespace {
25472558
}
25482559

25492560
template <class AttrClass>
2550-
AttrClass *getWithoutClaiming(TypeAttrSet *attrs) {
2561+
std::enable_if_t<std::is_base_of_v<TypeAttribute, AttrClass>, AttrClass *>
2562+
getWithoutClaiming(TypeAttrSet *attrs) {
25512563
return (attrs ? getWithoutClaiming<AttrClass>(*attrs) : nullptr);
25522564
}
2565+
2566+
template <class AttrClass>
2567+
std::enable_if_t<std::is_same_v<AttrClass, CallerIsolatedTypeRepr>,
2568+
CallerIsolatedTypeRepr *>
2569+
getWithoutClaiming(TypeAttrSet *attrs) {
2570+
return attrs ? attrs->getNonisolatedNonsendingAttr() : nullptr;
2571+
}
25532572
} // end anonymous namespace
25542573

25552574
Type TypeResolution::resolveContextualType(
@@ -4247,10 +4266,19 @@ NeverNullType TypeResolver::resolveASTFunctionType(
42474266
};
42484267

42494268
if (auto concurrentAttr = claim<ConcurrentTypeAttr>(attrs)) {
4269+
if (auto *nonisolatedNonsendingAttr =
4270+
getWithoutClaiming<CallerIsolatedTypeRepr>(attrs)) {
4271+
diagnoseInvalid(
4272+
nonisolatedNonsendingAttr, nonisolatedNonsendingAttr->getStartLoc(),
4273+
diag::cannot_use_nonisolated_nonsending_together_with_concurrent,
4274+
nonisolatedNonsendingAttr);
4275+
}
4276+
42504277
checkExecutionBehaviorAttribute(concurrentAttr);
4278+
42514279
if (!repr->isInvalid())
42524280
isolation = FunctionTypeIsolation::forNonIsolated();
4253-
} else {
4281+
} else if (!getWithoutClaiming<CallerIsolatedTypeRepr>(attrs)) {
42544282
if (ctx.LangOpts.getFeatureState(Feature::NonisolatedNonsendingByDefault)
42554283
.isEnabledForMigration()) {
42564284
// Diagnose only in the interface stage, which is run once.
@@ -5281,7 +5309,20 @@ TypeResolver::resolveSendingTypeRepr(SendingTypeRepr *repr,
52815309
NeverNullType
52825310
TypeResolver::resolveCallerIsolatedTypeRepr(CallerIsolatedTypeRepr *repr,
52835311
TypeResolutionOptions options) {
5284-
Type type = resolveType(repr->getBase(), options);
5312+
Type type;
5313+
{
5314+
TypeAttrSet attrs(getASTContext(), repr);
5315+
5316+
auto *baseRepr = repr->getBase();
5317+
if (auto *attrRepr = dyn_cast<AttributedTypeRepr>(baseRepr)) {
5318+
baseRepr = attrs.accumulate(attrRepr);
5319+
}
5320+
5321+
type = resolveAttributedType(baseRepr, options, attrs);
5322+
5323+
attrs.diagnoseUnclaimed(resolution, options, type);
5324+
}
5325+
52855326
if (type->hasError())
52865327
return ErrorType::get(getASTContext());
52875328

@@ -5297,15 +5338,6 @@ TypeResolver::resolveCallerIsolatedTypeRepr(CallerIsolatedTypeRepr *repr,
52975338
diag::nonisolated_nonsending_only_on_async, repr);
52985339
}
52995340

5300-
if (auto *ATR = dyn_cast<AttributedTypeRepr>(repr->getBase())) {
5301-
if (ATR->get(TypeAttrKind::Concurrent)) {
5302-
diagnoseInvalid(
5303-
repr, repr->getStartLoc(),
5304-
diag::cannot_use_nonisolated_nonsending_together_with_concurrent,
5305-
repr);
5306-
}
5307-
}
5308-
53095341
switch (fnType->getIsolation().getKind()) {
53105342
case FunctionTypeIsolation::Kind::NonIsolated:
53115343
break;

test/Concurrency/attr_execution/adoption_mode.swift

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ struct G<T> {
1212
// MARK: Functions
1313
do {
1414
func syncF() {}
15-
@concurrent func executionConcurrentAsyncF() async {}
16-
nonisolated(nonsending) func executionCallerAsyncF() async {}
15+
@concurrent func concurrentAsyncF() async {}
16+
nonisolated(nonsending) func nonisolatedNonsendingAsyncF() async {}
1717
@MainActor func mainActorAsyncF() async {}
1818
func isolatedParamAsyncF(
1919
isolation: isolated (any Actor)? = #isolation
@@ -24,13 +24,15 @@ do {
2424

2525
struct S {
2626
init(sync: ()) {}
27-
@concurrent init(executionAsync: ()) async {}
27+
@concurrent init(concurrentAsync: ()) async {}
28+
nonisolated(nonsending) init(nonisolatedNonsendingAsync: ()) async {}
2829
@MainActor init(mainActorAsync: ()) async {}
2930
// expected-warning@+1:5 {{feature 'NonisolatedNonsendingByDefault' will cause nonisolated async initializer 'init' to run on the caller's actor; use @concurrent to preserve behavior}}{{5-5=@concurrent }}{{none}}
3031
init(async: ()) async {}
3132

3233
func syncF() {}
33-
@concurrent func executionAsyncF() async {}
34+
@concurrent func concurrentAsyncF() async {}
35+
nonisolated(nonsending) func nonisolatedNonsendingAsyncF() async {}
3436
@MainActor func mainActorAsyncF() async {}
3537
// expected-warning@+2:17 {{feature 'NonisolatedNonsendingByDefault' will cause nonisolated async instance method 'asyncF' to run on the caller's actor; use @concurrent to preserve behavior}}{{-1:5-5=@concurrent }}{{none}}
3638
nonisolated
@@ -39,13 +41,15 @@ do {
3941

4042
protocol P {
4143
init(sync: ())
42-
@concurrent init(executionAsync: ()) async
44+
@concurrent init(concurrentAsync: ()) async
45+
nonisolated(nonsending) init(nonisolatedNonsendingAsync: ()) async
4346
@MainActor init(mainActorAsync: ()) async
4447
// expected-warning@+1:5 {{feature 'NonisolatedNonsendingByDefault' will cause nonisolated async initializer 'init' to run on the caller's actor; use @concurrent to preserve behavior}}{{5-5=@concurrent }}{{none}}
4548
init(async: ()) async
4649

4750
func syncF()
48-
@concurrent func executionAsyncF() async
51+
@concurrent func concurrentAsyncF() async
52+
nonisolated(nonsending) func nonisolatedNonsendingAsyncF() async
4953
@MainActor func mainActorAsyncF() async
5054
// expected-warning@+1:10 {{feature 'NonisolatedNonsendingByDefault' will cause nonisolated async instance method 'asyncF' to run on the caller's actor; use @concurrent to preserve behavior}}{{5-5=@concurrent }}{{none}}
5155
func asyncF() async
@@ -54,13 +58,15 @@ do {
5458
protocol Functions {}
5559
extension Functions {
5660
init(sync: ()) {}
57-
@concurrent init(executionAsync: ()) async {}
61+
@concurrent init(concurrentAsync: ()) async {}
62+
nonisolated(nonsending) init(nonisolatedNonsendingAsync: ()) async {}
5863
@MainActor init(mainActorAsync: ()) async {}
5964
// expected-warning@+1:3 {{feature 'NonisolatedNonsendingByDefault' will cause nonisolated async initializer 'init' to run on the caller's actor; use @concurrent to preserve behavior}}{{3-3=@concurrent }}{{none}}
6065
init(async: ()) async {}
6166

6267
func syncF() {}
63-
@concurrent func executionAsyncF() async {}
68+
@concurrent func concurrentAsyncF() async {}
69+
nonisolated(nonsending) func nonisolatedNonsendingAsyncF() async {}
6470
@MainActor func mainActorAsyncF() async {}
6571
// expected-warning@+1:8 {{feature 'NonisolatedNonsendingByDefault' will cause nonisolated async instance method 'asyncF' to run on the caller's actor; use @concurrent to preserve behavior}}{{3-3=@concurrent }}{{none}}
6672
func asyncF() async {}
@@ -75,8 +81,11 @@ do {
7581
var syncS: Int { get {} set {} }
7682
subscript(syncS _: Int) -> Int { get {} }
7783

78-
@concurrent var executionAsyncS: Int { get async {} }
79-
@concurrent subscript(executionAsyncS _: Int) -> Int { get async {} }
84+
@concurrent var concurrentAsyncS: Int { get async {} }
85+
@concurrent subscript(concurrentAsyncS _: Int) -> Int { get async {} }
86+
87+
nonisolated(nonsending) var nonisolatedNonsendingAsyncS: Int { get async {} }
88+
nonisolated(nonsending) subscript(nonisolatedNonsendingAsyncS _: Int) -> Int { get async {} }
8089

8190
@MainActor var mainActorAsyncS: Int { get async {} }
8291
@MainActor subscript(mainActorAsyncS _: Int) -> Int { get async {} }
@@ -95,8 +104,11 @@ do {
95104
var syncS: Int { get }
96105
subscript(syncS _: Int) -> Int { get }
97106

98-
@concurrent var executionAsyncS: Int { get async }
99-
@concurrent subscript(executionAsyncS _: Int) -> Int { get async }
107+
@concurrent var concurrentAsyncS: Int { get async }
108+
@concurrent subscript(concurrentAsyncS _: Int) -> Int { get async }
109+
110+
nonisolated(nonsending) var nonisolatedNonsendingAsyncS: Int { get async }
111+
nonisolated(nonsending) subscript(nonisolatedNonsendingAsyncS _: Int) -> Int { get async }
100112

101113
@MainActor var mainActorAsyncS: Int { get async }
102114
@MainActor subscript(mainActorAsyncS _: Int) -> Int { get async }
@@ -112,8 +124,11 @@ extension Storage {
112124
var syncS: Int { get {} set {} }
113125
subscript(syncS _: Int) -> Int { get {} }
114126

115-
@concurrent var executionAsyncS: Int { get async {} }
116-
@concurrent subscript(executionAsyncS _: Int) -> Int { get async {} }
127+
@concurrent var concurrentAsyncS: Int { get async {} }
128+
@concurrent subscript(concurrentAsyncS _: Int) -> Int { get async {} }
129+
130+
nonisolated(nonsending) var nonisolatedNonsendingAsyncS: Int { get async {} }
131+
nonisolated(nonsending) subscript(nonisolatedNonsendingAsyncS _: Int) -> Int { get async {} }
117132

118133
@MainActor var mainActorAsyncS: Int { get async {} }
119134
@MainActor subscript(mainActorAsyncS _: Int) -> Int { get async {} }
@@ -134,7 +149,8 @@ do {
134149
enum E {
135150
case esac(
136151
sync: () -> Void,
137-
executionAsync: @concurrent () async -> Void,
152+
concurrentAsync: @concurrent () async -> Void,
153+
nonisolatedNonsendingAsync: nonisolated(nonsending) () async -> Void,
138154
mainActorAsync: @MainActor () async -> Void,
139155
// expected-warning@+1:14 {{feature 'NonisolatedNonsendingByDefault' will cause nonisolated async function type to be treated as specified to run on the caller's actor; use @concurrent to preserve behavior}}{{14-14=@concurrent }}{{none}}
140156
async: () async -> Void,
@@ -146,7 +162,8 @@ do {
146162
struct S {
147163
subscript(
148164
sync: () -> Void,
149-
executionAsync: @concurrent () async -> Void,
165+
concurrentAsync: @concurrent () async -> Void,
166+
nonisolatedNonsendingAsync: nonisolated(nonsending) () async -> Void,
150167
mainActorAsync: @MainActor () async -> Void,
151168
// expected-warning@+1:14 {{feature 'NonisolatedNonsendingByDefault' will cause nonisolated async function type to be treated as specified to run on the caller's actor; use @concurrent to preserve behavior}}{{14-14=@concurrent }}{{none}}
152169
async: () async -> Void,
@@ -159,7 +176,8 @@ do {
159176

160177
func foo(
161178
sync: () -> Void,
162-
executionAsync: @concurrent () async -> Void,
179+
concurrentAsync: @concurrent () async -> Void,
180+
nonisolatedNonsendingAsync: nonisolated(nonsending) () async -> Void,
163181
mainActorAsync: @MainActor () async -> Void,
164182
// expected-warning@+1:12 {{feature 'NonisolatedNonsendingByDefault' will cause nonisolated async function type to be treated as specified to run on the caller's actor; use @concurrent to preserve behavior}}{{12-12=@concurrent }}{{none}}
165183
async: () async -> Void,
@@ -169,7 +187,8 @@ do {
169187

170188
let _ = { (
171189
sync: () -> Void,
172-
executionAsync: @concurrent () async -> Void,
190+
concurrentAsync: @concurrent () async -> Void,
191+
nonisolatedNonsendingAsync: nonisolated(nonsending) () async -> Void,
173192
mainActorAsync: @MainActor () async -> Void,
174193
// expected-warning@+1:12 {{feature 'NonisolatedNonsendingByDefault' will cause nonisolated async function type to be treated as specified to run on the caller's actor; use @concurrent to preserve behavior}}{{12-12=@concurrent }}{{none}}
175194
async: () async -> Void,
@@ -183,7 +202,8 @@ do {
183202
do {
184203
struct G<T> {
185204
struct Sync where T == () -> Void {}
186-
struct ExecutionAsync where T == @concurrent () async -> Void {}
205+
struct ConcurrentAsync where T == @concurrent () async -> Void {}
206+
struct NonisolatedNonsendingAsync where T == nonisolated(nonsending) () async -> Void {}
187207
struct MainActorAsync where T == @MainActor () async -> Void {}
188208
// expected-warning@+1:29 {{feature 'NonisolatedNonsendingByDefault' will cause nonisolated async function type to be treated as specified to run on the caller's actor; use @concurrent to preserve behavior}}{{29-29=@concurrent }}{{none}}
189209
struct Async where T == () async -> Void {}
@@ -196,6 +216,7 @@ do {
196216
do {
197217
let _: () -> Void
198218
let _: @concurrent () async -> Void
219+
let _: nonisolated(nonsending) () async -> Void
199220
let _: @MainActor () async -> Void
200221
// expected-warning@+1:10 {{feature 'NonisolatedNonsendingByDefault' will cause nonisolated async function type to be treated as specified to run on the caller's actor; use @concurrent to preserve behavior}}{{10-10=@concurrent }}{{none}}
201222
let _: () async -> Void
@@ -209,6 +230,7 @@ do {
209230

210231
let _ = anything as? () -> Void
211232
let _ = anything as? @concurrent () async -> Void
233+
let _ = anything as? nonisolated(nonsending) () async -> Void
212234
let _ = anything as? @MainActor () async -> Void
213235
// expected-warning@+1:24 {{feature 'NonisolatedNonsendingByDefault' will cause nonisolated async function type to be treated as specified to run on the caller's actor; use @concurrent to preserve behavior}}{{24-24=@concurrent }}{{none}}
214236
let _ = anything as? () async -> Void

0 commit comments

Comments
 (0)