Skip to content

Commit b24b088

Browse files
authored
Merge pull request #75668 from hborla/actor-isolation-inference-source
[Concurrency] Compute the source of actor isolation in `ActorIsolationRequest`.
2 parents 66303f6 + 5fa35b5 commit b24b088

14 files changed

+344
-62
lines changed

include/swift/AST/ActorIsolation.h

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,13 @@ class ActorIsolation {
275275
void print(llvm::raw_ostream &os) const;
276276

277277
void printForSIL(llvm::raw_ostream &os) const;
278-
278+
279+
/// Print the given isolation for diagnostics. If \c asNoun is \c false,
280+
/// the participle adjective form is printed, e.g. "main actor-isolated".
281+
/// Otherwise, the noun form is printed, e.g. "main actor isolation".
279282
void printForDiagnostics(llvm::raw_ostream &os,
280-
StringRef openingQuotationMark = "'") const;
283+
StringRef openingQuotationMark = "'",
284+
bool asNoun = false) const;
281285

282286
SWIFT_DEBUG_DUMPER(dump());
283287

@@ -287,9 +291,68 @@ class ActorIsolation {
287291
SWIFT_DEBUG_DUMPER(dumpForDiagnostics());
288292
};
289293

294+
struct IsolationSource {
295+
enum Kind : uint8_t {
296+
/// Isolation is written in an explicit attribute.
297+
Explicit,
298+
/// Isolation is inferred from the enclosing lexical context.
299+
LexicalContext,
300+
/// Isolation is inferred from conformance to a protocol.
301+
Conformance,
302+
/// Isolation is inherited from a superclass.
303+
Superclass,
304+
/// Isolation is inferred from an overridden superclass method.
305+
Override,
306+
/// Isolation is inferred from \c @main.
307+
MainFunction,
308+
/// Isolation is inferred in top-level code.
309+
TopLevelCode,
310+
/// Unspecified isolation, which defaults to \c nonisolated.
311+
None,
312+
};
313+
314+
using InferenceSource =
315+
llvm::PointerUnion<Decl *, AbstractClosureExpr *>;
316+
317+
/// The declaration with the original isolation attribute.
318+
InferenceSource inferenceSource;
319+
Kind kind;
320+
321+
IsolationSource(InferenceSource inferenceSource = nullptr,
322+
Kind kind = Kind::None)
323+
: inferenceSource(inferenceSource), kind(kind) {}
324+
325+
bool isInferred() const {
326+
return (kind != None) && (kind != Explicit);
327+
}
328+
329+
void printForDiagnostics(llvm::raw_ostream &os,
330+
StringRef openingQuotationMark = "'") const;
331+
};
332+
333+
struct InferredActorIsolation {
334+
ActorIsolation isolation;
335+
IsolationSource source;
336+
337+
static InferredActorIsolation forUnspecified() {
338+
return {
339+
ActorIsolation::forUnspecified(),
340+
IsolationSource()
341+
};
342+
}
343+
344+
bool preconcurrency() const {
345+
return isolation.preconcurrency();
346+
}
347+
};
348+
290349
/// Determine how the given value declaration is isolated.
291350
ActorIsolation getActorIsolation(ValueDecl *value);
292351

352+
/// Infer the actor isolation of the given declaration, including
353+
/// the source of isolation inference.
354+
InferredActorIsolation getInferredActorIsolation(ValueDecl *value);
355+
293356
/// Trampoline for AbstractClosureExpr::getActorIsolation.
294357
ActorIsolation
295358
__AbstractClosureExpr_getActorIsolation(AbstractClosureExpr *CE);

include/swift/AST/DiagnosticEngine.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ namespace swift {
140140
VersionTuple,
141141
LayoutConstraint,
142142
ActorIsolation,
143+
IsolationSource,
143144
Diagnostic,
144145
ClangDecl
145146
};
@@ -175,6 +176,7 @@ namespace swift {
175176
llvm::VersionTuple VersionVal;
176177
LayoutConstraint LayoutConstraintVal;
177178
ActorIsolation ActorIsolationVal;
179+
IsolationSource IsolationSourceVal;
178180
DiagnosticInfo *DiagnosticVal;
179181
const clang::NamedDecl *ClangDecl;
180182
};
@@ -283,6 +285,11 @@ namespace swift {
283285
ActorIsolationVal(AI) {
284286
}
285287

288+
DiagnosticArgument(IsolationSource IS)
289+
: Kind(DiagnosticArgumentKind::IsolationSource),
290+
IsolationSourceVal(IS){
291+
}
292+
286293
DiagnosticArgument(DiagnosticInfo *D)
287294
: Kind(DiagnosticArgumentKind::Diagnostic),
288295
DiagnosticVal(D) {
@@ -402,6 +409,11 @@ namespace swift {
402409
return ActorIsolationVal;
403410
}
404411

412+
IsolationSource getAsIsolationSource() const {
413+
assert(Kind == DiagnosticArgumentKind::IsolationSource);
414+
return IsolationSourceVal;
415+
}
416+
405417
DiagnosticInfo *getAsDiagnostic() const {
406418
assert(Kind == DiagnosticArgumentKind::Diagnostic);
407419
return DiagnosticVal;

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5535,6 +5535,10 @@ NOTE(actor_isolated_sync_func_value,none,
55355535
"calls function of type %0 from outside of its actor context are "
55365536
"implicitly asynchronous",
55375537
(Type))
5538+
NOTE(actor_isolation_source,none,
5539+
"%noun0 inferred from %1",
5540+
(ActorIsolation, IsolationSource))
5541+
55385542
NOTE(note_distributed_actor_isolated_method,none,
55395543
"distributed actor-isolated %kind0 declared here",
55405544
(const ValueDecl *))

include/swift/AST/TypeCheckRequests.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,15 +1536,16 @@ class GlobalActorAttributeRequest
15361536
/// Determine the actor isolation for the given declaration.
15371537
class ActorIsolationRequest :
15381538
public SimpleRequest<ActorIsolationRequest,
1539-
ActorIsolation(ValueDecl *),
1539+
InferredActorIsolation(ValueDecl *),
15401540
RequestFlags::Cached> {
15411541
public:
15421542
using SimpleRequest::SimpleRequest;
15431543

15441544
private:
15451545
friend SimpleRequest;
15461546

1547-
ActorIsolation evaluate(Evaluator &evaluator, ValueDecl *value) const;
1547+
InferredActorIsolation evaluate(Evaluator &evaluator,
1548+
ValueDecl *value) const;
15481549

15491550
public:
15501551
// Caching

lib/AST/Decl.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11295,10 +11295,15 @@ bool VarDecl::isSelfParamCaptureIsolated() const {
1129511295
}
1129611296

1129711297
ActorIsolation swift::getActorIsolation(ValueDecl *value) {
11298+
return getInferredActorIsolation(value).isolation;
11299+
}
11300+
11301+
InferredActorIsolation
11302+
swift::getInferredActorIsolation(ValueDecl *value) {
1129811303
auto &ctx = value->getASTContext();
1129911304
return evaluateOrDefault(
1130011305
ctx.evaluator, ActorIsolationRequest{value},
11301-
ActorIsolation::forUnspecified());
11306+
InferredActorIsolation::forUnspecified());
1130211307
}
1130311308

1130411309
ActorIsolation swift::getActorIsolationOfContext(

lib/AST/DiagnosticEngine.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1012,8 +1012,16 @@ static void formatDiagnosticArgument(StringRef Modifier,
10121012
<< FormatOpts.ClosingQuotationMark;
10131013
break;
10141014
case DiagnosticArgumentKind::ActorIsolation: {
1015-
assert(Modifier.empty() && "Improper modifier for ActorIsolation argument");
1015+
assert((Modifier.empty() || Modifier == "noun") &&
1016+
"Improper modifier for ActorIsolation argument");
10161017
auto isolation = Arg.getAsActorIsolation();
1018+
isolation.printForDiagnostics(Out, FormatOpts.OpeningQuotationMark,
1019+
/*asNoun*/ Modifier == "noun");
1020+
break;
1021+
}
1022+
case DiagnosticArgumentKind::IsolationSource: {
1023+
assert(Modifier.empty() && "Improper modifier for IsolationSource argument");
1024+
auto isolation = Arg.getAsIsolationSource();
10171025
isolation.printForDiagnostics(Out, FormatOpts.OpeningQuotationMark);
10181026
break;
10191027
}

lib/AST/TypeCheckRequests.cpp

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1804,19 +1804,20 @@ ActorIsolation ActorIsolation::subst(SubstitutionMap subs) const {
18041804
}
18051805

18061806
void ActorIsolation::printForDiagnostics(llvm::raw_ostream &os,
1807-
StringRef openingQuotationMark) const {
1807+
StringRef openingQuotationMark,
1808+
bool asNoun) const {
18081809
switch (*this) {
18091810
case ActorIsolation::ActorInstance:
1810-
os << "actor-isolated";
1811+
os << "actor" << (asNoun ? " isolation" : "-isolated");
18111812
break;
18121813

18131814
case ActorIsolation::GlobalActor: {
18141815
if (isMainActor()) {
1815-
os << "main actor-isolated";
1816+
os << "main actor" << (asNoun ? " isolation" : "-isolated");
18161817
} else {
18171818
Type globalActor = getGlobalActor();
18181819
os << "global actor " << openingQuotationMark << globalActor.getString()
1819-
<< openingQuotationMark << "-isolated";
1820+
<< openingQuotationMark << (asNoun ? " isolation" : "-isolated");
18201821
}
18211822
break;
18221823
}
@@ -1942,6 +1943,52 @@ void swift::simple_display(
19421943
}
19431944
}
19441945

1946+
void IsolationSource::printForDiagnostics(
1947+
llvm::raw_ostream &os,
1948+
StringRef openingQuotationMark) const {
1949+
switch (this->kind) {
1950+
case IsolationSource::Explicit:
1951+
os << "explicit isolation";
1952+
return;
1953+
1954+
case IsolationSource::None:
1955+
os << "unspecified isolation";
1956+
return;
1957+
1958+
case IsolationSource::MainFunction:
1959+
os << "@main";
1960+
return;
1961+
1962+
case IsolationSource::TopLevelCode:
1963+
os << "top-level code";
1964+
return;
1965+
1966+
case IsolationSource::LexicalContext:
1967+
os << "enclosing context";
1968+
return;
1969+
1970+
case IsolationSource::Override:
1971+
os << "overridden superclass method";
1972+
return;
1973+
1974+
case IsolationSource::Conformance:
1975+
os << "conformance to ";
1976+
break;
1977+
1978+
case IsolationSource::Superclass:
1979+
os << "inheritance from ";
1980+
break;
1981+
}
1982+
1983+
auto *decl = inferenceSource.dyn_cast<Decl *>();
1984+
os << Decl::getDescriptiveKindName(decl->getDescriptiveKind());
1985+
if (auto *vd = dyn_cast<ValueDecl>(decl)) {
1986+
os << " " << openingQuotationMark;
1987+
vd->getName().printPretty(os);
1988+
os << openingQuotationMark;
1989+
}
1990+
}
1991+
19451992
bool swift::areTypesEqual(Type type1, Type type2) {
19461993
if (!type1 || !type2)
19471994
return !type1 && !type2;

0 commit comments

Comments
 (0)