Skip to content

Commit 5aa40dd

Browse files
committed
Extend DefaultArgumentKind with cases for nil, [], and [:].
Under -enable-infer-default-arguments, the Clang importer infers some default arguments for imported declarations. Rather than jumping through awful hoops to make sure that we create default argument generators (which will likely imply eager type checking), simply handle these cases as callee-side expansions. This makes -enable-infer-default-arguments usable, fixing rdar://problem/24049927.
1 parent bb181f6 commit 5aa40dd

File tree

18 files changed

+263
-122
lines changed

18 files changed

+263
-122
lines changed

include/swift/AST/DefaultArgumentKind.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,16 @@
1717
#ifndef SWIFT_DEFAULTARGUMENTKIND_H
1818
#define SWIFT_DEFAULTARGUMENTKIND_H
1919

20+
namespace llvm {
21+
class StringRef;
22+
}
23+
2024
namespace swift {
2125

26+
class Expr;
27+
2228
/// Describes the kind of default argument a tuple pattern element has.
23-
enum class DefaultArgumentKind {
29+
enum class DefaultArgumentKind : unsigned {
2430
/// No default argument.
2531
None,
2632
/// A normal default argument.
@@ -38,8 +44,22 @@ enum class DefaultArgumentKind {
3844
Function,
3945
/// The __DSO_HANDLE__ default argument, which is expanded at the call site.
4046
DSOHandle,
47+
/// The "nil" literal.
48+
Nil,
49+
/// An empty array literal.
50+
EmptyArray,
51+
/// An empty dictionary literal.
52+
EmptyDictionary,
4153
};
4254

55+
/// Retrieve the spelling of this default argument in source code, or
56+
/// an empty string if it has none.
57+
llvm::StringRef getDefaultArgumentSpelling(DefaultArgumentKind kind);
58+
59+
/// Infer a default argument kind from an expression, if the
60+
/// expression is the canonical way to spell that default argument.
61+
DefaultArgumentKind inferDefaultArgumentKind(Expr *expr);
62+
4363
} // end namespace swift
4464

4565
#endif // LLVM_SWIFT_DEFAULTARGUMENTKIND_H

include/swift/AST/Types.h

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -835,17 +835,6 @@ class alignas(1 << TypeAlignInBits) TypeBase {
835835
/// Retrieve the type declaration directly referenced by this type, if any.
836836
TypeDecl *getDirectlyReferencedTypeDecl() const;
837837

838-
/// Retrieve the default argument string that would be inferred for this type,
839-
/// assuming that we know it is inferred.
840-
///
841-
/// This routine pre-supposes that we know that the given type is the type of
842-
/// a parameter that has a default, and all we need to figure out is which
843-
/// default argument should be print.
844-
///
845-
/// FIXME: This should go away when/if inferred default arguments become
846-
/// "real".
847-
StringRef getInferredDefaultArgString();
848-
849838
private:
850839
// Make vanilla new/delete illegal for Types.
851840
void *operator new(size_t Bytes) throw() = delete;
@@ -1253,9 +1242,11 @@ class TupleTypeElt {
12531242
/// is variadic.
12541243
llvm::PointerIntPair<Identifier, 1, bool> NameAndVariadic;
12551244

1256-
/// \brief This is the type of the field, which is mandatory, along with the
1257-
/// kind of default argument.
1258-
llvm::PointerIntPair<Type, 3, DefaultArgumentKind> TyAndDefaultArg;
1245+
/// \brief This is the type of the field.
1246+
Type ElementType;
1247+
1248+
/// The default argument,
1249+
DefaultArgumentKind DefaultArg;
12591250

12601251
friend class TupleType;
12611252

@@ -1269,22 +1260,20 @@ class TupleTypeElt {
12691260

12701261
/*implicit*/ TupleTypeElt(TypeBase *Ty)
12711262
: NameAndVariadic(Identifier(), false),
1272-
TyAndDefaultArg(Ty, DefaultArgumentKind::None) { }
1263+
ElementType(Ty), DefaultArg(DefaultArgumentKind::None) { }
12731264

12741265
bool hasName() const { return !NameAndVariadic.getPointer().empty(); }
12751266
Identifier getName() const { return NameAndVariadic.getPointer(); }
12761267

1277-
Type getType() const { return TyAndDefaultArg.getPointer(); }
1268+
Type getType() const { return ElementType.getPointer(); }
12781269

12791270
/// Determine whether this field is variadic.
12801271
bool isVararg() const {
12811272
return NameAndVariadic.getInt();
12821273
}
12831274

12841275
/// Retrieve the kind of default argument available on this field.
1285-
DefaultArgumentKind getDefaultArgKind() const {
1286-
return TyAndDefaultArg.getInt();
1287-
}
1276+
DefaultArgumentKind getDefaultArgKind() const { return DefaultArg; }
12881277

12891278
/// Whether we have a default argument.
12901279
bool hasDefaultArg() const {
@@ -4366,7 +4355,7 @@ inline TupleTypeElt::TupleTypeElt(Type ty,
43664355
DefaultArgumentKind defArg,
43674356
bool isVariadic)
43684357
: NameAndVariadic(name, isVariadic),
4369-
TyAndDefaultArg(ty.getPointer(), defArg)
4358+
ElementType(ty), DefaultArg(defArg)
43704359
{
43714360
assert(!isVariadic ||
43724361
isa<ErrorType>(ty.getPointer()) ||

include/swift/Serialization/ModuleFormat.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,7 @@ const uint16_t VERSION_MAJOR = 0;
5151
/// To ensure that two separate changes don't silently get merged into one
5252
/// in source control, you should also update the comment to briefly
5353
/// describe what change you made.
54-
///
55-
/// Last change: Added support for multiple @_semantic attributes on
56-
/// SILFunctions.
57-
const uint16_t VERSION_MINOR = 226;
54+
const uint16_t VERSION_MINOR = 227; /// default argument kind expansion
5855

5956
using DeclID = Fixnum<31>;
6057
using DeclIDField = BCFixed<31>;
@@ -269,8 +266,11 @@ enum class DefaultArgumentKind : uint8_t {
269266
Function,
270267
Inherited,
271268
DSOHandle,
269+
Nil,
270+
EmptyArray,
271+
EmptyDictionary,
272272
};
273-
using DefaultArgumentField = BCFixed<3>;
273+
using DefaultArgumentField = BCFixed<4>;
274274

275275
// These IDs must \em not be renumbered or reordered without incrementing
276276
// VERSION_MAJOR.

lib/AST/ASTContext.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2343,7 +2343,8 @@ void TupleType::Profile(llvm::FoldingSetNodeID &ID,
23432343
ID.AddInteger(Fields.size());
23442344
for (const TupleTypeElt &Elt : Fields) {
23452345
ID.AddPointer(Elt.NameAndVariadic.getOpaqueValue());
2346-
ID.AddPointer(Elt.TyAndDefaultArg.getOpaqueValue());
2346+
ID.AddPointer(Elt.getType().getPointer());
2347+
ID.AddInteger(static_cast<unsigned>(Elt.getDefaultArgKind()));
23472348
}
23482349
}
23492350

lib/AST/ASTDumper.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,15 @@ namespace {
806806
case DefaultArgumentKind::Line:
807807
printField("default_arg", "__LINE__");
808808
break;
809+
case DefaultArgumentKind::Nil:
810+
printField("default_arg", "nil");
811+
break;
812+
case DefaultArgumentKind::EmptyArray:
813+
printField("default_arg", "[]");
814+
break;
815+
case DefaultArgumentKind::EmptyDictionary:
816+
printField("default_arg", "[:]");
817+
break;
809818
case DefaultArgumentKind::Normal:
810819
printField("default_arg", "normal");
811820
break;
@@ -2547,6 +2556,18 @@ namespace {
25472556
printField("default_arg", "__LINE__");
25482557
break;
25492558

2559+
case DefaultArgumentKind::Nil:
2560+
printField("default_arg", "nil");
2561+
break;
2562+
2563+
case DefaultArgumentKind::EmptyArray:
2564+
printField("default_arg", "[]");
2565+
break;
2566+
2567+
case DefaultArgumentKind::EmptyDictionary:
2568+
printField("default_arg", "[:]");
2569+
break;
2570+
25502571
case DefaultArgumentKind::Normal:
25512572
printField("default_arg", "normal");
25522573
break;

lib/AST/ASTPrinter.cpp

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,18 +1655,14 @@ void PrintAST::printOneParameter(const ParamDecl *param, bool Curried,
16551655

16561656
if (Options.PrintDefaultParameterPlaceholder &&
16571657
param->isDefaultArgument()) {
1658-
// For Clang declarations, figure out the default we're using.
1659-
auto AFD = dyn_cast<AbstractFunctionDecl>(param->getDeclContext());
1660-
if (AFD && AFD->getClangDecl() && param->hasType()) {
1661-
auto CurrType = param->getType();
1662-
Printer << " = " << CurrType->getInferredDefaultArgString();
1663-
} else {
1664-
// Use placeholder anywhere else.
1665-
Printer << " = default";
1666-
}
1658+
Printer << " = ";
1659+
auto defaultArgStr
1660+
= getDefaultArgumentSpelling(param->getDefaultArgumentKind());
1661+
if (defaultArgStr.empty())
1662+
Printer << "default";
1663+
else
1664+
Printer << defaultArgStr;
16671665
}
1668-
1669-
16701666
}
16711667

16721668
void PrintAST::printParameterList(ParameterList *PL, bool isCurried,

lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ add_swift_library(swiftAST
1414
ConformanceLookupTable.cpp
1515
Decl.cpp
1616
DeclContext.cpp
17+
DefaultArgumentKind.cpp
1718
DiagnosticList.cpp
1819
DiagnosticEngine.cpp
1920
DocComment.cpp

lib/AST/DefaultArgumentKind.cpp

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//===--- DefaultArgumentKind.cpp - Default Argument Implementation --------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file implements utilities associated with default arguments.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
#include "swift/AST/DefaultArgumentKind.h"
17+
#include "swift/AST/ASTContext.h"
18+
#include "swift/AST/Decl.h"
19+
#include "swift/AST/Expr.h"
20+
using namespace swift;
21+
22+
StringRef swift::getDefaultArgumentSpelling(DefaultArgumentKind kind) {
23+
switch (kind) {
24+
case DefaultArgumentKind::None:
25+
case DefaultArgumentKind::Normal:
26+
case DefaultArgumentKind::Inherited:
27+
return StringRef();
28+
29+
case DefaultArgumentKind::File:
30+
return "__FILE__";
31+
32+
case DefaultArgumentKind::Line:
33+
return "__LINE__";
34+
35+
case DefaultArgumentKind::Column:
36+
return "__COLUMN__";
37+
38+
case DefaultArgumentKind::Function:
39+
return "__FUNCTION__";
40+
41+
case DefaultArgumentKind::DSOHandle:
42+
return "__DSO_HANDLE__";
43+
44+
case DefaultArgumentKind::Nil:
45+
return "nil";
46+
47+
case DefaultArgumentKind::EmptyArray:
48+
return "[]";
49+
50+
case DefaultArgumentKind::EmptyDictionary:
51+
return "[:]";
52+
}
53+
}
54+
55+
DefaultArgumentKind swift::inferDefaultArgumentKind(Expr *expr) {
56+
if (auto call = dyn_cast<CallExpr>(expr)) {
57+
if (auto ctorRefCall = dyn_cast<ConstructorRefCallExpr>(call->getFn())) {
58+
if (auto ctorRef = dyn_cast<DeclRefExpr>(ctorRefCall->getFn())) {
59+
if (auto ctor = dyn_cast<ConstructorDecl>(ctorRef->getDecl())) {
60+
auto ctorArg = call->getArg()->getSemanticsProvidingExpr();
61+
62+
// __FILE__, __LINE__, __COLUMN__, __FUNCTION__, __DSO_HANDLE__.
63+
if (auto magic = dyn_cast<MagicIdentifierLiteralExpr>(ctorArg)) {
64+
switch (magic->getKind()) {
65+
case MagicIdentifierLiteralExpr::File:
66+
return DefaultArgumentKind::File;
67+
case MagicIdentifierLiteralExpr::Line:
68+
return DefaultArgumentKind::Line;
69+
case MagicIdentifierLiteralExpr::Column:
70+
return DefaultArgumentKind::Column;
71+
case MagicIdentifierLiteralExpr::Function:
72+
return DefaultArgumentKind::Function;
73+
case MagicIdentifierLiteralExpr::DSOHandle:
74+
return DefaultArgumentKind::DSOHandle;
75+
}
76+
}
77+
78+
// nil.
79+
if (ctor->getFullName().getArgumentNames().size() == 1 &&
80+
ctor->getFullName().getArgumentNames()[0]
81+
== ctor->getASTContext().Id_nilLiteral)
82+
return DefaultArgumentKind::Nil;
83+
}
84+
}
85+
}
86+
}
87+
88+
// Empty array literals, [].
89+
if (auto arrayExpr = dyn_cast<ArrayExpr>(expr)) {
90+
if (arrayExpr->getElements().empty())
91+
return DefaultArgumentKind::EmptyArray;
92+
93+
return DefaultArgumentKind::None;
94+
}
95+
96+
// Empty dictionary literals, [:].
97+
if (auto dictionaryExpr = dyn_cast<DictionaryExpr>(expr)) {
98+
if (dictionaryExpr->getElements().empty())
99+
return DefaultArgumentKind::EmptyDictionary;
100+
101+
return DefaultArgumentKind::None;
102+
}
103+
104+
return DefaultArgumentKind::None;
105+
}
106+

lib/AST/Type.cpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -924,22 +924,6 @@ TypeDecl *TypeBase::getDirectlyReferencedTypeDecl() const {
924924
return nullptr;
925925
}
926926

927-
StringRef TypeBase::getInferredDefaultArgString() {
928-
if (auto structDecl = getStructOrBoundGenericStruct()) {
929-
if (structDecl->getClangDecl()) {
930-
for (auto attr : structDecl->getAttrs()) {
931-
if (auto synthesizedProto = dyn_cast<SynthesizedProtocolAttr>(attr)) {
932-
if (synthesizedProto->getProtocolKind()
933-
== KnownProtocolKind::OptionSetType)
934-
return "[]";
935-
}
936-
}
937-
}
938-
}
939-
940-
return "nil";
941-
}
942-
943927
/// \brief Collect the protocols in the existential type T into the given
944928
/// vector.
945929
static void addProtocols(Type T, SmallVectorImpl<ProtocolDecl *> &Protocols) {

0 commit comments

Comments
 (0)