Skip to content

Commit a55283d

Browse files
committed
Sema: Lazy synthesis of implicit constructors in non-primary files
1 parent 6c012b2 commit a55283d

File tree

1 file changed

+56
-43
lines changed

1 file changed

+56
-43
lines changed

lib/Sema/CodeSynthesis.cpp

Lines changed: 56 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2264,44 +2264,42 @@ ConstructorDecl *swift::createImplicitConstructor(TypeChecker &tc,
22642264
ctor->getAttrs().add(new (tc.Context) OverrideAttr(/*IsImplicit=*/true));
22652265
}
22662266

2267-
// Type-check the constructor declaration.
2268-
tc.validateDecl(ctor);
2269-
22702267
return ctor;
22712268
}
22722269

22732270
/// Create a stub body that emits a fatal error message.
2274-
static void createStubBody(TypeChecker &tc, ConstructorDecl *ctor) {
2275-
auto unimplementedInitDecl = tc.Context.getUnimplementedInitializerDecl();
2271+
static void synthesizeStubBody(AbstractFunctionDecl *fn, void *) {
2272+
auto *ctor = cast<ConstructorDecl>(fn);
2273+
auto &ctx = ctor->getASTContext();
2274+
2275+
auto unimplementedInitDecl = ctx.getUnimplementedInitializerDecl();
22762276
auto classDecl = ctor->getDeclContext()->getSelfClassDecl();
22772277
if (!unimplementedInitDecl) {
2278-
tc.diagnose(classDecl->getLoc(), diag::missing_unimplemented_init_runtime);
2278+
ctx.Diags.diagnose(classDecl->getLoc(),
2279+
diag::missing_unimplemented_init_runtime);
22792280
return;
22802281
}
22812282

22822283
// Create a call to Swift._unimplementedInitializer
22832284
auto loc = classDecl->getLoc();
2284-
Expr *fn = new (tc.Context) DeclRefExpr(unimplementedInitDecl,
2285-
DeclNameLoc(loc),
2286-
/*Implicit=*/true);
2285+
Expr *ref = new (ctx) DeclRefExpr(unimplementedInitDecl,
2286+
DeclNameLoc(loc),
2287+
/*Implicit=*/true);
22872288

22882289
llvm::SmallString<64> buffer;
2289-
StringRef fullClassName = tc.Context.AllocateCopy(
2290+
StringRef fullClassName = ctx.AllocateCopy(
22902291
(classDecl->getModuleContext()->getName().str() +
22912292
"." +
22922293
classDecl->getName().str()).toStringRef(buffer));
22932294

2294-
Expr *className = new (tc.Context) StringLiteralExpr(fullClassName, loc,
2295-
/*Implicit=*/true);
2296-
Expr *call = CallExpr::createImplicit(tc.Context, fn, { className },
2297-
{ tc.Context.Id_className });
2298-
ctor->setBody(BraceStmt::create(tc.Context, SourceLoc(),
2295+
Expr *className = new (ctx) StringLiteralExpr(fullClassName, loc,
2296+
/*Implicit=*/true);
2297+
Expr *call = CallExpr::createImplicit(ctx, ref, { className },
2298+
{ ctx.Id_className });
2299+
ctor->setBody(BraceStmt::create(ctx, SourceLoc(),
22992300
ASTNode(call),
23002301
SourceLoc(),
23012302
/*implicit=*/true));
2302-
2303-
// Note that this is a stub implementation.
2304-
ctor->setStubImplementation(true);
23052303
}
23062304

23072305
static std::tuple<GenericEnvironment *, GenericParamList *, SubstitutionMap>
@@ -2476,6 +2474,39 @@ configureInheritedDesignatedInitAttributes(TypeChecker &tc,
24762474
ctor->getAttrs().add(new (ctx) NonObjCAttr(/*isImplicit=*/true));
24772475
}
24782476

2477+
static void synthesizeDesignatedInitOverride(AbstractFunctionDecl *fn,
2478+
void *context) {
2479+
auto *ctor = cast<ConstructorDecl>(fn);
2480+
auto &ctx = ctor->getASTContext();
2481+
2482+
auto *bodyParams = ctor->getParameters();
2483+
auto *superclassCtor = (ConstructorDecl *) context;
2484+
2485+
// Reference to super.init.
2486+
auto *selfDecl = ctor->getImplicitSelfDecl();
2487+
Expr *superRef = new (ctx) SuperRefExpr(selfDecl, SourceLoc(),
2488+
/*Implicit=*/true);
2489+
Expr *ctorRef = new (ctx) UnresolvedDotExpr(superRef, SourceLoc(),
2490+
superclassCtor->getFullName(),
2491+
DeclNameLoc(),
2492+
/*Implicit=*/true);
2493+
2494+
auto ctorArgs = buildArgumentForwardingExpr(bodyParams->getArray(), ctx);
2495+
2496+
Expr *superCall =
2497+
CallExpr::create(ctx, ctorRef, ctorArgs,
2498+
superclassCtor->getFullName().getArgumentNames(), { },
2499+
/*hasTrailingClosure=*/false, /*implicit=*/true);
2500+
if (superclassCtor->hasThrows()) {
2501+
superCall = new (ctx) TryExpr(SourceLoc(), superCall, Type(),
2502+
/*implicit=*/true);
2503+
}
2504+
ctor->setBody(BraceStmt::create(ctx, SourceLoc(),
2505+
ASTNode(superCall),
2506+
SourceLoc(),
2507+
/*implicit=*/true));
2508+
}
2509+
24792510
ConstructorDecl *
24802511
swift::createDesignatedInitOverride(TypeChecker &tc,
24812512
ClassDecl *classDecl,
@@ -2556,37 +2587,19 @@ swift::createDesignatedInitOverride(TypeChecker &tc,
25562587

25572588
if (kind == DesignatedInitKind::Stub) {
25582589
// Make this a stub implementation.
2559-
createStubBody(tc, ctor);
2590+
ctor->setBodySynthesizer(synthesizeStubBody);
2591+
2592+
// Note that this is a stub implementation.
2593+
ctor->setStubImplementation(true);
2594+
2595+
// Stub constructors don't appear in the vtable.
25602596
ctor->setNeedsNewVTableEntry(false);
25612597
return ctor;
25622598
}
25632599

25642600
// Form the body of a chaining designated initializer.
25652601
assert(kind == DesignatedInitKind::Chaining);
2566-
2567-
// Reference to super.init.
2568-
auto *selfDecl = ctor->getImplicitSelfDecl();
2569-
Expr *superRef = new (ctx) SuperRefExpr(selfDecl, SourceLoc(),
2570-
/*Implicit=*/true);
2571-
Expr *ctorRef = new (ctx) UnresolvedDotExpr(superRef, SourceLoc(),
2572-
superclassCtor->getFullName(),
2573-
DeclNameLoc(),
2574-
/*Implicit=*/true);
2575-
2576-
auto ctorArgs = buildArgumentForwardingExpr(bodyParams->getArray(), ctx);
2577-
2578-
Expr *superCall =
2579-
CallExpr::create(ctx, ctorRef, ctorArgs,
2580-
superclassCtor->getFullName().getArgumentNames(), { },
2581-
/*hasTrailingClosure=*/false, /*implicit=*/true);
2582-
if (superclassCtor->hasThrows()) {
2583-
superCall = new (ctx) TryExpr(SourceLoc(), superCall, Type(),
2584-
/*implicit=*/true);
2585-
}
2586-
ctor->setBody(BraceStmt::create(tc.Context, SourceLoc(),
2587-
ASTNode(superCall),
2588-
SourceLoc(),
2589-
/*implicit=*/true));
2602+
ctor->setBodySynthesizer(synthesizeDesignatedInitOverride, superclassCtor);
25902603

25912604
return ctor;
25922605
}

0 commit comments

Comments
 (0)