Skip to content

Commit 71a2adb

Browse files
authored
Check default arguments even if a function has no body (#18864)
This is needed for textual interfaces, but the behavior doesn't have to be specific to that, since functions without bodies don't come up in other situations.
1 parent 3b2c55f commit 71a2adb

File tree

5 files changed

+36
-43
lines changed

5 files changed

+36
-43
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3123,12 +3123,12 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
31233123
}
31243124
}
31253125

3126-
if (FD->hasBody()) {
3127-
// Record the body.
3128-
TC.definedFunctions.push_back(FD);
3129-
} else if (requiresDefinition(FD)) {
3126+
if (requiresDefinition(FD) && !FD->hasBody()) {
31303127
// Complain if we should have a body.
31313128
TC.diagnose(FD->getLoc(), diag::func_decl_without_brace);
3129+
} else {
3130+
// Record the body.
3131+
TC.definedFunctions.push_back(FD);
31323132
}
31333133
}
31343134

@@ -3354,20 +3354,18 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
33543354
AccessControlChecker::checkAccessControl(TC, CD);
33553355
UsableFromInlineChecker::checkUsableFromInline(TC, CD);
33563356

3357-
if (CD->hasBody() && !CD->isMemberwiseInitializer()) {
3358-
TC.definedFunctions.push_back(CD);
3359-
} else if (requiresDefinition(CD)) {
3357+
if (requiresDefinition(CD) && !CD->hasBody()) {
33603358
// Complain if we should have a body.
33613359
TC.diagnose(CD->getLoc(), diag::missing_initializer_def);
3360+
} else {
3361+
TC.definedFunctions.push_back(CD);
33623362
}
33633363
}
33643364

33653365
void visitDestructorDecl(DestructorDecl *DD) {
33663366
TC.validateDecl(DD);
33673367
TC.checkDeclAttributes(DD);
3368-
3369-
if (DD->hasBody())
3370-
TC.definedFunctions.push_back(DD);
3368+
TC.definedFunctions.push_back(DD);
33713369
}
33723370
};
33733371
} // end anonymous namespace

lib/Sema/TypeCheckStmt.cpp

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,6 +1537,7 @@ void TypeChecker::checkDefaultArguments(ParameterList *params,
15371537
bool TypeChecker::typeCheckAbstractFunctionBodyUntil(AbstractFunctionDecl *AFD,
15381538
SourceLoc EndTypeCheckLoc) {
15391539
validateDecl(AFD);
1540+
checkDefaultArguments(AFD->getParameters(), AFD);
15401541

15411542
if (!AFD->getBody())
15421543
return false;
@@ -1558,9 +1559,6 @@ bool TypeChecker::typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD) {
15581559
if (AFD->isBodyTypeChecked())
15591560
return false;
15601561

1561-
if (!AFD->getBody())
1562-
return false;
1563-
15641562
FrontendStatsTracer StatsTracer(Context.Stats, "typecheck-fn", AFD);
15651563
PrettyStackTraceDecl StackEntry("type-checking", AFD);
15661564

@@ -1579,17 +1577,16 @@ bool TypeChecker::typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD) {
15791577
if (error)
15801578
return true;
15811579

1582-
performAbstractFuncDeclDiagnostics(*this, AFD);
1580+
if (AFD->getBody())
1581+
performAbstractFuncDeclDiagnostics(*this, AFD);
1582+
15831583
return false;
15841584
}
15851585

15861586
// Type check a function body (defined with the func keyword) that is either a
15871587
// named function or an anonymous func expression.
15881588
bool TypeChecker::typeCheckFunctionBodyUntil(FuncDecl *FD,
15891589
SourceLoc EndTypeCheckLoc) {
1590-
// Check the default argument definitions.
1591-
checkDefaultArguments(FD->getParameters(), FD);
1592-
15931590
// Clang imported inline functions do not have a Swift body to
15941591
// typecheck.
15951592
if (FD->getClangDecl())
@@ -1692,12 +1689,8 @@ static bool isKnownEndOfConstructor(ASTNode N) {
16921689

16931690
bool TypeChecker::typeCheckConstructorBodyUntil(ConstructorDecl *ctor,
16941691
SourceLoc EndTypeCheckLoc) {
1695-
// Check the default argument definitions.
1696-
checkDefaultArguments(ctor->getParameters(), ctor);
1697-
16981692
BraceStmt *body = ctor->getBody();
1699-
if (!body)
1700-
return true;
1693+
assert(body);
17011694

17021695
// For constructors, we make sure that the body ends with a "return" stmt,
17031696
// which we either implicitly synthesize, or the user can write. This
@@ -1826,8 +1819,7 @@ bool TypeChecker::typeCheckDestructorBodyUntil(DestructorDecl *DD,
18261819
StmtChecker SC(*this, static_cast<AbstractFunctionDecl *>(DD));
18271820
SC.EndTypeCheckLoc = EndTypeCheckLoc;
18281821
BraceStmt *Body = DD->getBody();
1829-
if (!Body)
1830-
return false;
1822+
assert(Body);
18311823

18321824
bool HadError = SC.typeCheckBody(Body);
18331825

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
2+
3+
class SomeClass {
4+
// Has defaults, but no body.
5+
public func hasDefaults(a: Int = 4, b: Int = 1 + 2)
6+
7+
// CHECK-LABEL: sil hidden @$S11DefaultArgs9SomeClassC11hasDefaults1a1bySi_SitFfA_
8+
// CHECK: integer_literal $Builtin.Int2048, 4
9+
// CHECK: end sil function '$S11DefaultArgs9SomeClassC11hasDefaults1a1bySi_SitFfA_'
10+
11+
// CHECK-LABEL: sil hidden @$S11DefaultArgs9SomeClassC11hasDefaults1a1bySi_SitFfA0_
12+
// CHECK: integer_literal $Builtin.Int2048, 1
13+
// CHECK: integer_literal $Builtin.Int2048, 2
14+
// CHECK: function_ref @$SSi1poiyS2i_SitFZ
15+
// CHECK: end sil function '$S11DefaultArgs9SomeClassC11hasDefaults1a1bySi_SitFfA0_'
16+
17+
public init(a: Int = 5)
18+
19+
// CHECK-LABEL: sil hidden @$S11DefaultArgs9SomeClassC1aACSi_tcfcfA_
20+
// CHECK: integer_literal $Builtin.Int2048, 5
21+
// CHECK: end sil function '$S11DefaultArgs9SomeClassC1aACSi_tcfcfA_'
22+
}

test/NameBinding/Inputs/MutualDependencyHelper.swift

Lines changed: 0 additions & 5 deletions
This file was deleted.

test/NameBinding/MutualDependency.swift

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)