Skip to content

Commit b941835

Browse files
authored
Merge pull request #35398 from kavon/async-initializers
2 parents c1328bd + 4a32b06 commit b941835

32 files changed

+699
-73
lines changed

include/swift/AST/Decl.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6769,15 +6769,18 @@ class ConstructorDecl : public AbstractFunctionDecl {
67696769
public:
67706770
ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
67716771
bool Failable, SourceLoc FailabilityLoc,
6772+
bool Async, SourceLoc AsyncLoc,
67726773
bool Throws, SourceLoc ThrowsLoc,
67736774
ParameterList *BodyParams,
67746775
GenericParamList *GenericParams,
67756776
DeclContext *Parent);
67766777

67776778
static ConstructorDecl *
67786779
createImported(ASTContext &ctx, ClangNode clangNode, DeclName name,
6779-
SourceLoc constructorLoc, bool failable,
6780-
SourceLoc failabilityLoc, bool throws, SourceLoc throwsLoc,
6780+
SourceLoc constructorLoc,
6781+
bool failable, SourceLoc failabilityLoc,
6782+
bool async, SourceLoc asyncLoc,
6783+
bool throws, SourceLoc throwsLoc,
67816784
ParameterList *bodyParams, GenericParamList *genericParams,
67826785
DeclContext *parent);
67836786

include/swift/AST/DiagnosticsParse.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,6 @@ ERROR(expected_dynamic_func_attr,none,
762762
ERROR(async_after_throws,none,
763763
"%select{'async'|'reasync'}0 must precede %select{'throws'|'rethrows'}1",
764764
(bool, bool))
765-
ERROR(async_init,none, "initializer cannot be marked 'async'", ())
766765
ERROR(duplicate_effects_specifier,none,
767766
"'%0' has already been specified", (StringRef))
768767

include/swift/AST/DiagnosticsSema.def

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2605,12 +2605,8 @@ ERROR(override_dynamic_self_mismatch,none,
26052605
ERROR(override_class_declaration_in_extension,none,
26062606
"cannot override a non-dynamic class declaration from an extension",
26072607
())
2608-
ERROR(override_throws,none,
2609-
"cannot override non-throwing %select{method|initializer}0 with "
2610-
"throwing %select{method|initializer}0", (bool))
2611-
// TODO: this really could be merged with the above.
26122608
ERROR(override_with_more_effects,none,
2613-
"cannot override non-'%1' %0 with '%1' %0",
2609+
"cannot override non-%1 %0 with %1 %0",
26142610
(DescriptiveDeclKind, StringRef))
26152611
ERROR(override_throws_objc,none,
26162612
"overriding a throwing @objc %select{method|initializer}0 with "
@@ -3903,6 +3899,11 @@ ERROR(return_init_non_nil,none,
39033899
"'nil' is the only return value permitted in an initializer",
39043900
())
39053901

3902+
ERROR(implicit_async_super_init,none,
3903+
"missing call to superclass's initializer; "
3904+
"'super.init' is 'async' and requires an explicit call",
3905+
())
3906+
39063907
WARNING(if_always_true,none,
39073908
"'if' condition is always true", ())
39083909
WARNING(while_always_true,none,
@@ -4285,7 +4286,7 @@ NOTE(note_add_globalactor_to_function,none,
42854286
(StringRef, DescriptiveDeclKind, DeclName, Type))
42864287
FIXIT(insert_globalactor_attr, "@%0 ", (Type))
42874288
ERROR(not_objc_function_async,none,
4288-
"'async' function cannot be represented in Objective-C", ())
4289+
"'async' %0 cannot be represented in Objective-C", (DescriptiveDeclKind))
42894290
NOTE(not_objc_function_type_async,none,
42904291
"'async' function types cannot be represented in Objective-C", ())
42914292
ERROR(actor_isolated_objc,none,

lib/AST/Decl.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7672,13 +7672,13 @@ bool FuncDecl::isMainTypeMainMethod() const {
76727672

76737673
ConstructorDecl::ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
76747674
bool Failable, SourceLoc FailabilityLoc,
7675-
bool Throws,
7676-
SourceLoc ThrowsLoc,
7675+
bool Async, SourceLoc AsyncLoc,
7676+
bool Throws, SourceLoc ThrowsLoc,
76777677
ParameterList *BodyParams,
76787678
GenericParamList *GenericParams,
76797679
DeclContext *Parent)
76807680
: AbstractFunctionDecl(DeclKind::Constructor, Parent, Name, ConstructorLoc,
7681-
/*Async=*/false, SourceLoc(), Throws, ThrowsLoc,
7681+
Async, AsyncLoc, Throws, ThrowsLoc,
76827682
/*HasImplicitSelfDecl=*/true,
76837683
GenericParams),
76847684
FailabilityLoc(FailabilityLoc),
@@ -7696,13 +7696,17 @@ ConstructorDecl::ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
76967696
ConstructorDecl *ConstructorDecl::createImported(
76977697
ASTContext &ctx, ClangNode clangNode, DeclName name,
76987698
SourceLoc constructorLoc, bool failable, SourceLoc failabilityLoc,
7699+
bool async, SourceLoc asyncLoc,
76997700
bool throws, SourceLoc throwsLoc, ParameterList *bodyParams,
77007701
GenericParamList *genericParams, DeclContext *parent) {
77017702
void *declPtr = allocateMemoryForDecl<ConstructorDecl>(
77027703
ctx, sizeof(ConstructorDecl), true);
77037704
auto ctor = ::new (declPtr)
7704-
ConstructorDecl(name, constructorLoc, failable, failabilityLoc, throws,
7705-
throwsLoc, bodyParams, genericParams, parent);
7705+
ConstructorDecl(name, constructorLoc,
7706+
failable, failabilityLoc,
7707+
async, asyncLoc,
7708+
throws, throwsLoc,
7709+
bodyParams, genericParams, parent);
77067710
ctor->setClangNode(clangNode);
77077711
return ctor;
77087712
}

lib/ClangImporter/ImportDecl.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ makeEnumRawValueConstructor(ClangImporter::Implementation &Impl,
535535
auto *ctorDecl =
536536
new (C) ConstructorDecl(name, enumDecl->getLoc(),
537537
/*Failable=*/true, /*FailabilityLoc=*/SourceLoc(),
538+
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
538539
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
539540
paramPL,
540541
/*GenericParams=*/nullptr, enumDecl);
@@ -1305,6 +1306,7 @@ createDefaultConstructor(ClangImporter::Implementation &Impl,
13051306
auto constructor = new (context) ConstructorDecl(
13061307
name, structDecl->getLoc(),
13071308
/*Failable=*/false, /*FailabilityLoc=*/SourceLoc(),
1309+
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
13081310
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), emptyPL,
13091311
/*GenericParams=*/nullptr, structDecl);
13101312

@@ -1432,6 +1434,7 @@ createValueConstructor(ClangImporter::Implementation &Impl,
14321434
auto constructor = new (context) ConstructorDecl(
14331435
name, structDecl->getLoc(),
14341436
/*Failable=*/false, /*FailabilityLoc=*/SourceLoc(),
1437+
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
14351438
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), paramList,
14361439
/*GenericParams=*/nullptr, structDecl);
14371440

@@ -4132,9 +4135,11 @@ namespace {
41324135
DeclName ctorName(Impl.SwiftContext, DeclBaseName::createConstructor(),
41334136
bodyParams);
41344137
result = Impl.createDeclWithClangNode<ConstructorDecl>(
4135-
clangNode, AccessLevel::Public, ctorName, loc, /*failable=*/false,
4136-
/*FailabilityLoc=*/SourceLoc(), /*Throws=*/false,
4137-
/*ThrowsLoc=*/SourceLoc(), bodyParams, genericParams, dc);
4138+
clangNode, AccessLevel::Public, ctorName, loc,
4139+
/*failable=*/false, /*FailabilityLoc=*/SourceLoc(),
4140+
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
4141+
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
4142+
bodyParams, genericParams, dc);
41384143
} else {
41394144
auto resultTy = importedType.getType();
41404145

@@ -6514,6 +6519,7 @@ Decl *SwiftDeclConverter::importGlobalAsInitializer(
65146519
auto result = Impl.createDeclWithClangNode<ConstructorDecl>(
65156520
decl, AccessLevel::Public, name, /*NameLoc=*/SourceLoc(),
65166521
failable, /*FailabilityLoc=*/SourceLoc(),
6522+
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
65176523
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), parameterList,
65186524
/*GenericParams=*/nullptr, dc);
65196525
result->setImplicitlyUnwrappedOptional(isIUO);
@@ -6998,6 +7004,7 @@ ConstructorDecl *SwiftDeclConverter::importConstructor(
69987004
auto result = Impl.createDeclWithClangNode<ConstructorDecl>(
69997005
objcMethod, AccessLevel::Public, importedName.getDeclName(),
70007006
/*NameLoc=*/SourceLoc(), failability, /*FailabilityLoc=*/SourceLoc(),
7007+
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
70017008
/*Throws=*/importedName.getErrorInfo().hasValue(),
70027009
/*ThrowsLoc=*/SourceLoc(), bodyParams,
70037010
/*GenericParams=*/nullptr, const_cast<DeclContext *>(dc));

lib/ClangImporter/ImportName.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,7 @@ NameImporter::considerAsyncImport(
12861286

12871287
// Initializers cannot be 'async'.
12881288
// FIXME: We might eventually allow this.
1289+
// TODO: should the restriction be lifted in ClangImporter?
12891290
if (isInitializer)
12901291
return notAsync("initializers cannot be async");
12911292

lib/Parse/ParseDecl.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8005,19 +8005,12 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
80058005
Attributes.add(new (Context) RethrowsAttr(throwsLoc));
80068006
}
80078007

8008-
// Initializers cannot be 'async'.
8009-
// FIXME: We should be able to lift this restriction.
8010-
if (asyncLoc.isValid()) {
8011-
diagnose(asyncLoc, diag::async_init)
8012-
.fixItRemove(asyncLoc);
8013-
asyncLoc = SourceLoc();
8014-
}
8015-
80168008
diagnoseWhereClauseInGenericParamList(GenericParams);
80178009

80188010
DeclName FullName(Context, DeclBaseName::createConstructor(), namePieces);
80198011
auto *CD = new (Context) ConstructorDecl(FullName, ConstructorLoc,
80208012
Failable, FailabilityLoc,
8013+
asyncLoc.isValid(), asyncLoc,
80218014
throwsLoc.isValid(), throwsLoc,
80228015
Params.get(), GenericParams,
80238016
CurDeclContext);

lib/SILGen/SILGenConstructor.cpp

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "ArgumentSource.h"
1414
#include "Conversion.h"
15+
#include "ExecutorBreadcrumb.h"
1516
#include "Initialization.h"
1617
#include "LValue.h"
1718
#include "RValue.h"
@@ -350,13 +351,20 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
350351
SILValue selfLV = VarLocs[selfDecl].value;
351352

352353
// Emit the prolog.
353-
emitProlog(ctor->getParameters(),
354-
/*selfParam=*/nullptr,
355-
ctor->getResultInterfaceType(), ctor,
356-
ctor->hasThrows(),
357-
ctor->getThrowsLoc());
354+
emitBasicProlog(ctor->getParameters(),
355+
/*selfParam=*/nullptr,
356+
ctor->getResultInterfaceType(), ctor,
357+
ctor->hasThrows(),
358+
ctor->getThrowsLoc());
358359
emitConstructorMetatypeArg(*this, ctor);
359360

361+
// Make sure we've hopped to the right global actor, if any.
362+
if (ctor->hasAsync()) {
363+
SILLocation prologueLoc(selfDecl);
364+
prologueLoc.markAsPrologue();
365+
emitConstructorPrologActorHop(prologueLoc, getActorIsolation(ctor));
366+
}
367+
360368
// Create a basic block to jump to for the implicit 'self' return.
361369
// We won't emit this until after we've emitted the body.
362370
// The epilog takes a void return because the return of 'self' is implicit.
@@ -662,6 +670,18 @@ static void emitDefaultActorInitialization(SILGenFunction &SGF,
662670
{ self.borrow(SGF, loc).getValue() });
663671
}
664672

673+
void SILGenFunction::emitConstructorPrologActorHop(
674+
SILLocation loc,
675+
Optional<ActorIsolation> maybeIso) {
676+
if (!maybeIso)
677+
return;
678+
679+
if (auto executor = emitExecutor(loc, *maybeIso, None)) {
680+
ExpectedExecutor = *executor;
681+
B.createHopToExecutor(loc, *executor);
682+
}
683+
}
684+
665685
void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
666686
MagicFunctionName = SILGenModule::getMagicFunctionName(ctor);
667687

@@ -717,13 +737,20 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
717737

718738
// Emit the prolog for the non-self arguments.
719739
// FIXME: Handle self along with the other body patterns.
720-
uint16_t ArgNo = emitProlog(ctor->getParameters(), /*selfParam=*/nullptr,
721-
TupleType::getEmpty(F.getASTContext()), ctor,
722-
ctor->hasThrows(), ctor->getThrowsLoc());
740+
uint16_t ArgNo = emitBasicProlog(ctor->getParameters(), /*selfParam=*/nullptr,
741+
TupleType::getEmpty(F.getASTContext()), ctor,
742+
ctor->hasThrows(), ctor->getThrowsLoc());
723743

724744
SILType selfTy = getLoweredLoadableType(selfDecl->getType());
725745
ManagedValue selfArg = B.createInputFunctionArgument(selfTy, selfDecl);
726746

747+
// Make sure we've hopped to the right global actor, if any.
748+
if (ctor->hasAsync() && !selfClassDecl->isActor()) {
749+
SILLocation prologueLoc(selfDecl);
750+
prologueLoc.markAsPrologue();
751+
emitConstructorPrologActorHop(prologueLoc, getActorIsolation(ctor));
752+
}
753+
727754
if (!NeedsBoxForSelf) {
728755
SILLocation PrologueLoc(selfDecl);
729756
PrologueLoc.markAsPrologue();

lib/SILGen/SILGenFunction.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -997,8 +997,8 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, VarDecl *var) {
997997
}
998998
}
999999

1000-
emitProlog(/*paramList*/ nullptr, /*selfParam*/ nullptr, interfaceType, dc,
1001-
/*throws=*/false, SourceLoc());
1000+
emitBasicProlog(/*paramList*/ nullptr, /*selfParam*/ nullptr,
1001+
interfaceType, dc, /*throws=*/ false,SourceLoc());
10021002
prepareEpilog(true, false, CleanupLocation(loc));
10031003

10041004
auto pbd = var->getParentPatternBinding();

lib/SILGen/SILGenFunction.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,17 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
839839
Optional<ActorIsolation> actorIso,
840840
Optional<ManagedValue> actorSelf);
841841

842+
/// A version of `emitHopToTargetActor` that is specialized to the needs
843+
/// of various types of ConstructorDecls, like class or value initializers,
844+
/// because their prolog emission is not the same as for regular functions.
845+
///
846+
/// This function emits the appropriate hop_to_executor for a constructor's
847+
/// prologue.
848+
///
849+
/// NOTE: this does not support actor initializers!
850+
void emitConstructorPrologActorHop(SILLocation loc,
851+
Optional<ActorIsolation> actorIso);
852+
842853
/// Emit the executor for the given actor isolation.
843854
Optional<SILValue> emitExecutor(SILLocation loc,
844855
ActorIsolation isolation,
@@ -876,10 +887,11 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
876887
ParameterList *paramList, ParamDecl *selfParam,
877888
DeclContext *DC, Type resultType,
878889
bool throws, SourceLoc throwsLoc);
879-
/// returns the number of variables in paramPatterns.
880-
uint16_t emitProlog(ParameterList *paramList, ParamDecl *selfParam,
881-
Type resultType, DeclContext *DC,
882-
bool throws, SourceLoc throwsLoc);
890+
/// A simpler version of emitProlog
891+
/// \returns the number of variables in paramPatterns.
892+
uint16_t emitBasicProlog(ParameterList *paramList, ParamDecl *selfParam,
893+
Type resultType, DeclContext *DC,
894+
bool throws, SourceLoc throwsLoc);
883895

884896
/// Create SILArguments in the entry block that bind a single value
885897
/// of the given parameter suitably for being forwarded.

lib/SILGen/SILGenProlog.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,8 @@ void SILGenFunction::emitProlog(CaptureInfo captureInfo,
411411
Type resultType,
412412
bool throws,
413413
SourceLoc throwsLoc) {
414-
uint16_t ArgNo = emitProlog(paramList, selfParam, resultType,
415-
DC, throws, throwsLoc);
414+
uint16_t ArgNo = emitBasicProlog(paramList, selfParam, resultType,
415+
DC, throws, throwsLoc);
416416

417417
// Emit the capture argument variables. These are placed last because they
418418
// become the first curry level of the SIL function.
@@ -733,12 +733,12 @@ static void emitIndirectResultParameters(SILGenFunction &SGF, Type resultType,
733733
(void)arg;
734734
}
735735

736-
uint16_t SILGenFunction::emitProlog(ParameterList *paramList,
737-
ParamDecl *selfParam,
738-
Type resultType,
739-
DeclContext *DC,
740-
bool throws,
741-
SourceLoc throwsLoc) {
736+
uint16_t SILGenFunction::emitBasicProlog(ParameterList *paramList,
737+
ParamDecl *selfParam,
738+
Type resultType,
739+
DeclContext *DC,
740+
bool throws,
741+
SourceLoc throwsLoc) {
742742
// Create the indirect result parameters.
743743
auto genericSig = DC->getGenericSignatureOfContext();
744744
resultType = resultType->getCanonicalType(genericSig);

lib/Sema/CSApply.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,11 @@ static ConcreteDeclRef generateDeclRefForSpecializedCXXFunctionTemplate(
141141
if (isa<ConstructorDecl>(oldDecl)) {
142142
DeclName ctorName(ctx, DeclBaseName::createConstructor(), newParamList);
143143
auto newCtorDecl = ConstructorDecl::createImported(
144-
ctx, specialized, ctorName, oldDecl->getLoc(), /*failable=*/false,
145-
/*failabilityLoc=*/SourceLoc(), /*throws=*/false,
146-
/*throwsLoc=*/SourceLoc(), newParamList, /*genericParams=*/nullptr,
144+
ctx, specialized, ctorName, oldDecl->getLoc(),
145+
/*failable=*/false, /*failabilityLoc=*/SourceLoc(),
146+
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
147+
/*throws=*/false, /*throwsLoc=*/SourceLoc(),
148+
newParamList, /*genericParams=*/nullptr,
147149
oldDecl->getDeclContext());
148150
return ConcreteDeclRef(newCtorDecl);
149151
}

lib/Sema/CodeSynthesis.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl,
319319
auto *ctor =
320320
new (ctx) ConstructorDecl(name, Loc,
321321
/*Failable=*/false, /*FailabilityLoc=*/SourceLoc(),
322+
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
322323
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
323324
paramList, /*GenericParams=*/nullptr, decl);
324325

@@ -744,6 +745,7 @@ createDesignatedInitOverride(ClassDecl *classDecl,
744745
classDecl->getBraces().Start,
745746
superclassCtor->isFailable(),
746747
/*FailabilityLoc=*/SourceLoc(),
748+
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
747749
/*Throws=*/superclassCtor->hasThrows(),
748750
/*ThrowsLoc=*/SourceLoc(),
749751
bodyParams, genericParams, classDecl);

lib/Sema/DerivedConformanceCodable.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,6 +1847,7 @@ static ValueDecl *deriveDecodable_init(DerivedConformance &derived) {
18471847
auto *initDecl =
18481848
new (C) ConstructorDecl(name, SourceLoc(),
18491849
/*Failable=*/false,SourceLoc(),
1850+
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
18501851
/*Throws=*/true, SourceLoc(), paramList,
18511852
/*GenericParams=*/nullptr, conformanceDC);
18521853
initDecl->setImplicit();

lib/Sema/DerivedConformanceCodingKey.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ static ValueDecl *deriveInitDecl(DerivedConformance &derived, Type paramType,
130130
auto *initDecl =
131131
new (C) ConstructorDecl(name, SourceLoc(),
132132
/*Failable=*/true, /*FailabilityLoc=*/SourceLoc(),
133+
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
133134
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
134135
paramList,
135136
/*GenericParams=*/nullptr, parentDC);

lib/Sema/DerivedConformanceRawRepresentable.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ deriveRawRepresentable_init(DerivedConformance &derived) {
425425
auto initDecl =
426426
new (C) ConstructorDecl(name, SourceLoc(),
427427
/*Failable=*/ true, /*FailabilityLoc=*/SourceLoc(),
428+
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
428429
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
429430
paramList,
430431
/*GenericParams=*/nullptr, parentDC);

0 commit comments

Comments
 (0)