Skip to content

[concurrency] allow type initializers to be 'async' #35398

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -6769,15 +6769,18 @@ class ConstructorDecl : public AbstractFunctionDecl {
public:
ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
bool Failable, SourceLoc FailabilityLoc,
bool Async, SourceLoc AsyncLoc,
bool Throws, SourceLoc ThrowsLoc,
ParameterList *BodyParams,
GenericParamList *GenericParams,
DeclContext *Parent);

static ConstructorDecl *
createImported(ASTContext &ctx, ClangNode clangNode, DeclName name,
SourceLoc constructorLoc, bool failable,
SourceLoc failabilityLoc, bool throws, SourceLoc throwsLoc,
SourceLoc constructorLoc,
bool failable, SourceLoc failabilityLoc,
bool async, SourceLoc asyncLoc,
bool throws, SourceLoc throwsLoc,
ParameterList *bodyParams, GenericParamList *genericParams,
DeclContext *parent);

Expand Down
1 change: 0 additions & 1 deletion include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,6 @@ ERROR(expected_dynamic_func_attr,none,
ERROR(async_after_throws,none,
"%select{'async'|'reasync'}0 must precede %select{'throws'|'rethrows'}1",
(bool, bool))
ERROR(async_init,none, "initializer cannot be marked 'async'", ())
ERROR(duplicate_effects_specifier,none,
"'%0' has already been specified", (StringRef))

Expand Down
13 changes: 7 additions & 6 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -2605,12 +2605,8 @@ ERROR(override_dynamic_self_mismatch,none,
ERROR(override_class_declaration_in_extension,none,
"cannot override a non-dynamic class declaration from an extension",
())
ERROR(override_throws,none,
"cannot override non-throwing %select{method|initializer}0 with "
"throwing %select{method|initializer}0", (bool))
// TODO: this really could be merged with the above.
ERROR(override_with_more_effects,none,
"cannot override non-'%1' %0 with '%1' %0",
"cannot override non-%1 %0 with %1 %0",
(DescriptiveDeclKind, StringRef))
ERROR(override_throws_objc,none,
"overriding a throwing @objc %select{method|initializer}0 with "
Expand Down Expand Up @@ -3903,6 +3899,11 @@ ERROR(return_init_non_nil,none,
"'nil' is the only return value permitted in an initializer",
())

ERROR(implicit_async_super_init,none,
"missing call to superclass's initializer; "
"'super.init' is 'async' and requires an explicit call",
())

WARNING(if_always_true,none,
"'if' condition is always true", ())
WARNING(while_always_true,none,
Expand Down Expand Up @@ -4285,7 +4286,7 @@ NOTE(note_add_globalactor_to_function,none,
(StringRef, DescriptiveDeclKind, DeclName, Type))
FIXIT(insert_globalactor_attr, "@%0 ", (Type))
ERROR(not_objc_function_async,none,
"'async' function cannot be represented in Objective-C", ())
"'async' %0 cannot be represented in Objective-C", (DescriptiveDeclKind))
NOTE(not_objc_function_type_async,none,
"'async' function types cannot be represented in Objective-C", ())
ERROR(actor_isolated_objc,none,
Expand Down
14 changes: 9 additions & 5 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7672,13 +7672,13 @@ bool FuncDecl::isMainTypeMainMethod() const {

ConstructorDecl::ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
bool Failable, SourceLoc FailabilityLoc,
bool Throws,
SourceLoc ThrowsLoc,
bool Async, SourceLoc AsyncLoc,
bool Throws, SourceLoc ThrowsLoc,
ParameterList *BodyParams,
GenericParamList *GenericParams,
DeclContext *Parent)
: AbstractFunctionDecl(DeclKind::Constructor, Parent, Name, ConstructorLoc,
/*Async=*/false, SourceLoc(), Throws, ThrowsLoc,
Async, AsyncLoc, Throws, ThrowsLoc,
/*HasImplicitSelfDecl=*/true,
GenericParams),
FailabilityLoc(FailabilityLoc),
Expand All @@ -7696,13 +7696,17 @@ ConstructorDecl::ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
ConstructorDecl *ConstructorDecl::createImported(
ASTContext &ctx, ClangNode clangNode, DeclName name,
SourceLoc constructorLoc, bool failable, SourceLoc failabilityLoc,
bool async, SourceLoc asyncLoc,
bool throws, SourceLoc throwsLoc, ParameterList *bodyParams,
GenericParamList *genericParams, DeclContext *parent) {
void *declPtr = allocateMemoryForDecl<ConstructorDecl>(
ctx, sizeof(ConstructorDecl), true);
auto ctor = ::new (declPtr)
ConstructorDecl(name, constructorLoc, failable, failabilityLoc, throws,
throwsLoc, bodyParams, genericParams, parent);
ConstructorDecl(name, constructorLoc,
failable, failabilityLoc,
async, asyncLoc,
throws, throwsLoc,
bodyParams, genericParams, parent);
ctor->setClangNode(clangNode);
return ctor;
}
Expand Down
13 changes: 10 additions & 3 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@ makeEnumRawValueConstructor(ClangImporter::Implementation &Impl,
auto *ctorDecl =
new (C) ConstructorDecl(name, enumDecl->getLoc(),
/*Failable=*/true, /*FailabilityLoc=*/SourceLoc(),
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
paramPL,
/*GenericParams=*/nullptr, enumDecl);
Expand Down Expand Up @@ -1305,6 +1306,7 @@ createDefaultConstructor(ClangImporter::Implementation &Impl,
auto constructor = new (context) ConstructorDecl(
name, structDecl->getLoc(),
/*Failable=*/false, /*FailabilityLoc=*/SourceLoc(),
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), emptyPL,
/*GenericParams=*/nullptr, structDecl);

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

Expand Down Expand Up @@ -4132,9 +4135,11 @@ namespace {
DeclName ctorName(Impl.SwiftContext, DeclBaseName::createConstructor(),
bodyParams);
result = Impl.createDeclWithClangNode<ConstructorDecl>(
clangNode, AccessLevel::Public, ctorName, loc, /*failable=*/false,
/*FailabilityLoc=*/SourceLoc(), /*Throws=*/false,
/*ThrowsLoc=*/SourceLoc(), bodyParams, genericParams, dc);
clangNode, AccessLevel::Public, ctorName, loc,
/*failable=*/false, /*FailabilityLoc=*/SourceLoc(),
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
bodyParams, genericParams, dc);
} else {
auto resultTy = importedType.getType();

Expand Down Expand Up @@ -6514,6 +6519,7 @@ Decl *SwiftDeclConverter::importGlobalAsInitializer(
auto result = Impl.createDeclWithClangNode<ConstructorDecl>(
decl, AccessLevel::Public, name, /*NameLoc=*/SourceLoc(),
failable, /*FailabilityLoc=*/SourceLoc(),
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), parameterList,
/*GenericParams=*/nullptr, dc);
result->setImplicitlyUnwrappedOptional(isIUO);
Expand Down Expand Up @@ -6998,6 +7004,7 @@ ConstructorDecl *SwiftDeclConverter::importConstructor(
auto result = Impl.createDeclWithClangNode<ConstructorDecl>(
objcMethod, AccessLevel::Public, importedName.getDeclName(),
/*NameLoc=*/SourceLoc(), failability, /*FailabilityLoc=*/SourceLoc(),
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
/*Throws=*/importedName.getErrorInfo().hasValue(),
/*ThrowsLoc=*/SourceLoc(), bodyParams,
/*GenericParams=*/nullptr, const_cast<DeclContext *>(dc));
Expand Down
1 change: 1 addition & 0 deletions lib/ClangImporter/ImportName.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1286,6 +1286,7 @@ NameImporter::considerAsyncImport(

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

Expand Down
9 changes: 1 addition & 8 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8005,19 +8005,12 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
Attributes.add(new (Context) RethrowsAttr(throwsLoc));
}

// Initializers cannot be 'async'.
// FIXME: We should be able to lift this restriction.
if (asyncLoc.isValid()) {
diagnose(asyncLoc, diag::async_init)
.fixItRemove(asyncLoc);
asyncLoc = SourceLoc();
}

diagnoseWhereClauseInGenericParamList(GenericParams);

DeclName FullName(Context, DeclBaseName::createConstructor(), namePieces);
auto *CD = new (Context) ConstructorDecl(FullName, ConstructorLoc,
Failable, FailabilityLoc,
asyncLoc.isValid(), asyncLoc,
throwsLoc.isValid(), throwsLoc,
Params.get(), GenericParams,
CurDeclContext);
Expand Down
43 changes: 35 additions & 8 deletions lib/SILGen/SILGenConstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "ArgumentSource.h"
#include "Conversion.h"
#include "ExecutorBreadcrumb.h"
#include "Initialization.h"
#include "LValue.h"
#include "RValue.h"
Expand Down Expand Up @@ -350,13 +351,20 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
SILValue selfLV = VarLocs[selfDecl].value;

// Emit the prolog.
emitProlog(ctor->getParameters(),
/*selfParam=*/nullptr,
ctor->getResultInterfaceType(), ctor,
ctor->hasThrows(),
ctor->getThrowsLoc());
emitBasicProlog(ctor->getParameters(),
/*selfParam=*/nullptr,
ctor->getResultInterfaceType(), ctor,
ctor->hasThrows(),
ctor->getThrowsLoc());
emitConstructorMetatypeArg(*this, ctor);

// Make sure we've hopped to the right global actor, if any.
if (ctor->hasAsync()) {
SILLocation prologueLoc(selfDecl);
prologueLoc.markAsPrologue();
emitConstructorPrologActorHop(prologueLoc, getActorIsolation(ctor));
}

// Create a basic block to jump to for the implicit 'self' return.
// We won't emit this until after we've emitted the body.
// The epilog takes a void return because the return of 'self' is implicit.
Expand Down Expand Up @@ -662,6 +670,18 @@ static void emitDefaultActorInitialization(SILGenFunction &SGF,
{ self.borrow(SGF, loc).getValue() });
}

void SILGenFunction::emitConstructorPrologActorHop(
SILLocation loc,
Optional<ActorIsolation> maybeIso) {
if (!maybeIso)
return;

if (auto executor = emitExecutor(loc, *maybeIso, None)) {
ExpectedExecutor = *executor;
B.createHopToExecutor(loc, *executor);
}
}

void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
MagicFunctionName = SILGenModule::getMagicFunctionName(ctor);

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

// Emit the prolog for the non-self arguments.
// FIXME: Handle self along with the other body patterns.
uint16_t ArgNo = emitProlog(ctor->getParameters(), /*selfParam=*/nullptr,
TupleType::getEmpty(F.getASTContext()), ctor,
ctor->hasThrows(), ctor->getThrowsLoc());
uint16_t ArgNo = emitBasicProlog(ctor->getParameters(), /*selfParam=*/nullptr,
TupleType::getEmpty(F.getASTContext()), ctor,
ctor->hasThrows(), ctor->getThrowsLoc());

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

// Make sure we've hopped to the right global actor, if any.
if (ctor->hasAsync() && !selfClassDecl->isActor()) {
SILLocation prologueLoc(selfDecl);
prologueLoc.markAsPrologue();
emitConstructorPrologActorHop(prologueLoc, getActorIsolation(ctor));
}

if (!NeedsBoxForSelf) {
SILLocation PrologueLoc(selfDecl);
PrologueLoc.markAsPrologue();
Expand Down
4 changes: 2 additions & 2 deletions lib/SILGen/SILGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -997,8 +997,8 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, VarDecl *var) {
}
}

emitProlog(/*paramList*/ nullptr, /*selfParam*/ nullptr, interfaceType, dc,
/*throws=*/false, SourceLoc());
emitBasicProlog(/*paramList*/ nullptr, /*selfParam*/ nullptr,
interfaceType, dc, /*throws=*/ false,SourceLoc());
prepareEpilog(true, false, CleanupLocation(loc));

auto pbd = var->getParentPatternBinding();
Expand Down
20 changes: 16 additions & 4 deletions lib/SILGen/SILGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,17 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
Optional<ActorIsolation> actorIso,
Optional<ManagedValue> actorSelf);

/// A version of `emitHopToTargetActor` that is specialized to the needs
/// of various types of ConstructorDecls, like class or value initializers,
/// because their prolog emission is not the same as for regular functions.
///
/// This function emits the appropriate hop_to_executor for a constructor's
/// prologue.
///
/// NOTE: this does not support actor initializers!
void emitConstructorPrologActorHop(SILLocation loc,
Optional<ActorIsolation> actorIso);

/// Emit the executor for the given actor isolation.
Optional<SILValue> emitExecutor(SILLocation loc,
ActorIsolation isolation,
Expand Down Expand Up @@ -876,10 +887,11 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
ParameterList *paramList, ParamDecl *selfParam,
DeclContext *DC, Type resultType,
bool throws, SourceLoc throwsLoc);
/// returns the number of variables in paramPatterns.
uint16_t emitProlog(ParameterList *paramList, ParamDecl *selfParam,
Type resultType, DeclContext *DC,
bool throws, SourceLoc throwsLoc);
/// A simpler version of emitProlog
/// \returns the number of variables in paramPatterns.
uint16_t emitBasicProlog(ParameterList *paramList, ParamDecl *selfParam,
Type resultType, DeclContext *DC,
bool throws, SourceLoc throwsLoc);

/// Create SILArguments in the entry block that bind a single value
/// of the given parameter suitably for being forwarded.
Expand Down
16 changes: 8 additions & 8 deletions lib/SILGen/SILGenProlog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -411,8 +411,8 @@ void SILGenFunction::emitProlog(CaptureInfo captureInfo,
Type resultType,
bool throws,
SourceLoc throwsLoc) {
uint16_t ArgNo = emitProlog(paramList, selfParam, resultType,
DC, throws, throwsLoc);
uint16_t ArgNo = emitBasicProlog(paramList, selfParam, resultType,
DC, throws, throwsLoc);

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

uint16_t SILGenFunction::emitProlog(ParameterList *paramList,
ParamDecl *selfParam,
Type resultType,
DeclContext *DC,
bool throws,
SourceLoc throwsLoc) {
uint16_t SILGenFunction::emitBasicProlog(ParameterList *paramList,
ParamDecl *selfParam,
Type resultType,
DeclContext *DC,
bool throws,
SourceLoc throwsLoc) {
// Create the indirect result parameters.
auto genericSig = DC->getGenericSignatureOfContext();
resultType = resultType->getCanonicalType(genericSig);
Expand Down
8 changes: 5 additions & 3 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,11 @@ static ConcreteDeclRef generateDeclRefForSpecializedCXXFunctionTemplate(
if (isa<ConstructorDecl>(oldDecl)) {
DeclName ctorName(ctx, DeclBaseName::createConstructor(), newParamList);
auto newCtorDecl = ConstructorDecl::createImported(
ctx, specialized, ctorName, oldDecl->getLoc(), /*failable=*/false,
/*failabilityLoc=*/SourceLoc(), /*throws=*/false,
/*throwsLoc=*/SourceLoc(), newParamList, /*genericParams=*/nullptr,
ctx, specialized, ctorName, oldDecl->getLoc(),
/*failable=*/false, /*failabilityLoc=*/SourceLoc(),
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
/*throws=*/false, /*throwsLoc=*/SourceLoc(),
newParamList, /*genericParams=*/nullptr,
oldDecl->getDeclContext());
return ConcreteDeclRef(newCtorDecl);
}
Expand Down
2 changes: 2 additions & 0 deletions lib/Sema/CodeSynthesis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl,
auto *ctor =
new (ctx) ConstructorDecl(name, Loc,
/*Failable=*/false, /*FailabilityLoc=*/SourceLoc(),
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
paramList, /*GenericParams=*/nullptr, decl);

Expand Down Expand Up @@ -744,6 +745,7 @@ createDesignatedInitOverride(ClassDecl *classDecl,
classDecl->getBraces().Start,
superclassCtor->isFailable(),
/*FailabilityLoc=*/SourceLoc(),
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
/*Throws=*/superclassCtor->hasThrows(),
/*ThrowsLoc=*/SourceLoc(),
bodyParams, genericParams, classDecl);
Expand Down
1 change: 1 addition & 0 deletions lib/Sema/DerivedConformanceCodable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1847,6 +1847,7 @@ static ValueDecl *deriveDecodable_init(DerivedConformance &derived) {
auto *initDecl =
new (C) ConstructorDecl(name, SourceLoc(),
/*Failable=*/false,SourceLoc(),
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
/*Throws=*/true, SourceLoc(), paramList,
/*GenericParams=*/nullptr, conformanceDC);
initDecl->setImplicit();
Expand Down
1 change: 1 addition & 0 deletions lib/Sema/DerivedConformanceCodingKey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ static ValueDecl *deriveInitDecl(DerivedConformance &derived, Type paramType,
auto *initDecl =
new (C) ConstructorDecl(name, SourceLoc(),
/*Failable=*/true, /*FailabilityLoc=*/SourceLoc(),
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
paramList,
/*GenericParams=*/nullptr, parentDC);
Expand Down
1 change: 1 addition & 0 deletions lib/Sema/DerivedConformanceRawRepresentable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ deriveRawRepresentable_init(DerivedConformance &derived) {
auto initDecl =
new (C) ConstructorDecl(name, SourceLoc(),
/*Failable=*/ true, /*FailabilityLoc=*/SourceLoc(),
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
paramList,
/*GenericParams=*/nullptr, parentDC);
Expand Down
Loading