Skip to content

Commit a953690

Browse files
committed
[SE-0111] Drop argument labels on references to function values.
When referencing a function in the type checker, drop argument labels when we don't need them to type-check an immediate call to that function. This provides the semantic behavior of SE-0111, e.g., references to functions as values produce unlabeled function types, without the representational change of actually dropping argument labels from the type system. At the moment, this only works for bare references to functions. It still needs to be pushed through more of the type checker and more AST nodes to work in the general case. Keep this work behind the frontend flag -suppress-argument-labels-in-types for now.
1 parent 8c7e75a commit a953690

23 files changed

+539
-124
lines changed

include/swift/AST/DeclNameLoc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ class DeclNameLoc {
7878
/// Whether the location information is invalid.
7979
bool isInvalid() const { return getBaseNameLoc().isInvalid(); }
8080

81+
/// Whether this was written as a compound name.
82+
bool isCompound() const { return NumArgumentLabels > 0; }
83+
8184
/// Retrieve the location of the base name.
8285
SourceLoc getBaseNameLoc() const {
8386
return getSourceLocs()[BaseNameIndex];

include/swift/AST/Expr.h

Lines changed: 90 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/CaptureInfo.h"
2121
#include "swift/AST/ConcreteDeclRef.h"
2222
#include "swift/AST/DeclNameLoc.h"
23+
#include "swift/AST/FunctionRefKind.h"
2324
#include "swift/AST/ProtocolConformanceRef.h"
2425
#include "swift/AST/TypeAlignments.h"
2526
#include "swift/AST/TypeLoc.h"
@@ -53,7 +54,7 @@ namespace swift {
5354
class PatternBindingDecl;
5455
class ParameterList;
5556
class EnumElementDecl;
56-
57+
5758
enum class ExprKind : uint8_t {
5859
#define EXPR(Id, Parent) Id,
5960
#define EXPR_RANGE(Id, FirstId, LastId) \
@@ -114,7 +115,7 @@ enum class AccessSemantics : unsigned char {
114115
/// polymorphism is expected.
115116
Ordinary,
116117
};
117-
118+
118119
/// Expr - Base class for all expressions in swift.
119120
class alignas(8) Expr {
120121
Expr(const Expr&) = delete;
@@ -164,10 +165,21 @@ class alignas(8) Expr {
164165
friend class DeclRefExpr;
165166
unsigned : NumExprBits;
166167
unsigned Semantics : 2; // an AccessSemantics
168+
unsigned FunctionRefKind : 2;
167169
};
168-
enum { NumDeclRefExprBits = NumExprBits + 2 };
170+
enum { NumDeclRefExprBits = NumExprBits + 4 };
169171
static_assert(NumDeclRefExprBits <= 32, "fits in an unsigned");
170172

173+
class UnresolvedDeclRefExprBitfields {
174+
friend class UnresolvedDeclRefExpr;
175+
unsigned : NumExprBits;
176+
unsigned DeclRefKind : 2;
177+
unsigned IsSpecialized : 1;
178+
unsigned FunctionRefKind : 2;
179+
};
180+
enum { NumUnresolvedDeclRefExprBits = NumExprBits + 5 };
181+
static_assert(NumUnresolvedDeclRefExprBits <= 32, "fits in an unsigned");
182+
171183
class MemberRefExprBitfields {
172184
friend class MemberRefExpr;
173185
unsigned : NumExprBits;
@@ -246,6 +258,15 @@ class alignas(8) Expr {
246258
enum { NumOverloadSetRefExprBits = NumExprBits };
247259
static_assert(NumOverloadSetRefExprBits <= 32, "fits in an unsigned");
248260

261+
class OverloadedDeclRefExprBitfields {
262+
friend class OverloadedDeclRefExpr;
263+
unsigned : NumOverloadSetRefExprBits;
264+
unsigned IsSpecialized : 1;
265+
unsigned FunctionRefKind : 2;
266+
};
267+
enum { NumOverloadedDeclRefExprBits = NumOverloadSetRefExprBits + 3 };
268+
static_assert(NumOverloadedDeclRefExprBits <= 32, "fits in an unsigned");
269+
249270
class BooleanLiteralExprBitfields {
250271
friend class BooleanLiteralExpr;
251272
unsigned : NumLiteralExprBits;
@@ -398,12 +419,14 @@ class alignas(8) Expr {
398419
NumberLiteralExprBitfields NumberLiteralExprBits;
399420
StringLiteralExprBitfields StringLiteralExprBits;
400421
DeclRefExprBitfields DeclRefExprBits;
422+
UnresolvedDeclRefExprBitfields UnresolvedDeclRefExprBits;
401423
TupleExprBitfields TupleExprBits;
402424
MemberRefExprBitfields MemberRefExprBits;
403425
SubscriptExprBitfields SubscriptExprBits;
404426
DynamicSubscriptExprBitfields DynamicSubscriptExprBits;
405427
UnresolvedMemberExprBitfields UnresolvedMemberExprBits;
406428
OverloadSetRefExprBitfields OverloadSetRefExprBits;
429+
OverloadedDeclRefExprBitfields OverloadedDeclRefExprBits;
407430
BooleanLiteralExprBitfields BooleanLiteralExprBits;
408431
MagicIdentifierLiteralExprBitfields MagicIdentifierLiteralExprBits;
409432
ObjectLiteralExprBitfields ObjectLiteralExprBits;
@@ -1212,6 +1235,9 @@ class DeclRefExpr : public Expr {
12121235
Type Ty = Type())
12131236
: Expr(ExprKind::DeclRef, Implicit, Ty), DOrSpecialized(D), Loc(Loc) {
12141237
DeclRefExprBits.Semantics = (unsigned) semantics;
1238+
DeclRefExprBits.FunctionRefKind =
1239+
static_cast<unsigned>(Loc.isCompound() ? FunctionRefKind::Compound
1240+
: FunctionRefKind::Unapplied);
12151241
}
12161242

12171243
/// Retrieve the declaration to which this expression refers.
@@ -1254,6 +1280,16 @@ class DeclRefExpr : public Expr {
12541280
SourceLoc getLoc() const { return Loc.getBaseNameLoc(); }
12551281
DeclNameLoc getNameLoc() const { return Loc; }
12561282

1283+
/// Retrieve the kind of function reference.
1284+
FunctionRefKind getFunctionRefKind() const {
1285+
return static_cast<FunctionRefKind>(DeclRefExprBits.FunctionRefKind);
1286+
}
1287+
1288+
/// Set the kind of function reference.
1289+
void setFunctionRefKind(FunctionRefKind refKind) {
1290+
DeclRefExprBits.FunctionRefKind = static_cast<unsigned>(refKind);
1291+
}
1292+
12571293
static bool classof(const Expr *E) {
12581294
return E->getKind() == ExprKind::DeclRef;
12591295
}
@@ -1388,26 +1424,42 @@ class OverloadSetRefExpr : public Expr {
13881424

13891425
/// OverloadedDeclRefExpr - A reference to an overloaded name that should
13901426
/// eventually be resolved (by overload resolution) to a value reference.
1391-
class OverloadedDeclRefExpr : public OverloadSetRefExpr {
1427+
class OverloadedDeclRefExpr final : public OverloadSetRefExpr {
13921428
DeclNameLoc Loc;
1393-
bool IsSpecialized = false;
13941429

13951430
public:
13961431
OverloadedDeclRefExpr(ArrayRef<ValueDecl*> Decls, DeclNameLoc Loc,
1432+
bool isSpecialized,
1433+
FunctionRefKind functionRefKind,
13971434
bool Implicit, Type Ty = Type())
1398-
: OverloadSetRefExpr(ExprKind::OverloadedDeclRef, Decls, Implicit, Ty),
1399-
Loc(Loc) { }
1435+
: OverloadSetRefExpr(ExprKind::OverloadedDeclRef, Decls, Implicit, Ty),
1436+
Loc(Loc) {
1437+
OverloadedDeclRefExprBits.IsSpecialized = isSpecialized;
1438+
OverloadedDeclRefExprBits.FunctionRefKind =
1439+
static_cast<unsigned>(functionRefKind);
1440+
}
14001441

14011442
DeclNameLoc getNameLoc() const { return Loc; }
14021443
SourceLoc getLoc() const { return Loc.getBaseNameLoc(); }
14031444
SourceRange getSourceRange() const { return Loc.getSourceRange(); }
14041445

1405-
void setSpecialized(bool specialized) { IsSpecialized = specialized; }
1406-
14071446
/// \brief Determine whether this declaration reference was immediately
14081447
/// specialized by <...>.
1409-
bool isSpecialized() const { return IsSpecialized; }
1410-
1448+
bool isSpecialized() const {
1449+
return OverloadedDeclRefExprBits.IsSpecialized;
1450+
}
1451+
1452+
/// Retrieve the kind of function reference.
1453+
FunctionRefKind getFunctionRefKind() const {
1454+
return static_cast<FunctionRefKind>(
1455+
OverloadedDeclRefExprBits.FunctionRefKind);
1456+
}
1457+
1458+
/// Set the kind of function reference.
1459+
void setFunctionRefKind(FunctionRefKind refKind) {
1460+
OverloadedDeclRefExprBits.FunctionRefKind = static_cast<unsigned>(refKind);
1461+
}
1462+
14111463
static bool classof(const Expr *E) {
14121464
return E->getKind() == ExprKind::OverloadedDeclRef;
14131465
}
@@ -1421,29 +1473,48 @@ class OverloadedDeclRefExpr : public OverloadSetRefExpr {
14211473
class UnresolvedDeclRefExpr : public Expr {
14221474
DeclName Name;
14231475
DeclNameLoc Loc;
1424-
DeclRefKind RefKind;
1425-
bool IsSpecialized = false;
14261476

14271477
public:
14281478
UnresolvedDeclRefExpr(DeclName name, DeclRefKind refKind, DeclNameLoc loc)
1429-
: Expr(ExprKind::UnresolvedDeclRef, /*Implicit=*/loc.isInvalid()),
1430-
Name(name), Loc(loc), RefKind(refKind) {
1479+
: Expr(ExprKind::UnresolvedDeclRef, /*Implicit=*/loc.isInvalid()),
1480+
Name(name), Loc(loc) {
1481+
UnresolvedDeclRefExprBits.DeclRefKind = static_cast<unsigned>(refKind);
1482+
UnresolvedDeclRefExprBits.IsSpecialized = false;
1483+
UnresolvedDeclRefExprBits.FunctionRefKind =
1484+
static_cast<unsigned>(Loc.isCompound() ? FunctionRefKind::Compound
1485+
: FunctionRefKind::Unapplied);
14311486
}
14321487

14331488
bool hasName() const { return static_cast<bool>(Name); }
14341489
DeclName getName() const { return Name; }
1435-
DeclRefKind getRefKind() const { return RefKind; }
14361490

1437-
void setSpecialized(bool specialized) { IsSpecialized = specialized; }
1491+
DeclRefKind getRefKind() const {
1492+
return static_cast<DeclRefKind>(UnresolvedDeclRefExprBits.DeclRefKind);
1493+
}
1494+
1495+
void setSpecialized(bool specialized) {
1496+
UnresolvedDeclRefExprBits.IsSpecialized = specialized;
1497+
}
14381498

14391499
/// \brief Determine whether this declaration reference was immediately
14401500
/// specialized by <...>.
1441-
bool isSpecialized() const { return IsSpecialized; }
1501+
bool isSpecialized() const { return UnresolvedDeclRefExprBits.IsSpecialized; }
1502+
1503+
/// Retrieve the kind of function reference.
1504+
FunctionRefKind getFunctionRefKind() const {
1505+
return static_cast<FunctionRefKind>(
1506+
UnresolvedDeclRefExprBits.FunctionRefKind);
1507+
}
1508+
1509+
/// Set the kind of function reference.
1510+
void setFunctionRefKind(FunctionRefKind refKind) {
1511+
UnresolvedDeclRefExprBits.FunctionRefKind = static_cast<unsigned>(refKind);
1512+
}
14421513

14431514
DeclNameLoc getNameLoc() const { return Loc; }
14441515

14451516
SourceRange getSourceRange() const { return Loc.getSourceRange(); }
1446-
1517+
14471518
static bool classof(const Expr *E) {
14481519
return E->getKind() == ExprKind::UnresolvedDeclRef;
14491520
}

include/swift/AST/FunctionRefKind.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//===--- FunctionRefKind.h - Function reference kind ------------*- C++ -*-===//
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 defines the FunctionRefKind enum, which is used to describe how
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_AST_FUNCTION_REF_KIND_H
18+
#define SWIFT_AST_FUNCTION_REF_KIND_H
19+
20+
namespace swift {
21+
22+
/// Describes how a function is referenced within an expression node,
23+
/// which dictates whether argument labels are part of the resulting
24+
/// function type or not.
25+
///
26+
/// How a function is referenced comes down to how it was spelled in
27+
/// the source code, e.g., was it called in the source code and was it
28+
/// spelled as a compound name.
29+
enum class FunctionRefKind : unsigned {
30+
/// The function was referenced using a bare function name (e.g.,
31+
/// 'f') and not directly called.
32+
Unapplied,
33+
/// The function was referenced using a bare function name and was
34+
/// directly applied once, e.g., "f(a: 1, b: 2)".
35+
SingleApply,
36+
/// The function was referenced using a bare function name and was
37+
/// directly applied two or more times, e.g., "g(x)(y)".
38+
DoubleApply,
39+
/// The function was referenced using a compound function name,
40+
/// e.g., "f(a:b:)".
41+
Compound,
42+
};
43+
44+
/// Produce a string describing a function reference kind, for
45+
/// debugging purposes.
46+
StringRef getFunctionRefKindStr(FunctionRefKind refKind);
47+
48+
}
49+
50+
#endif // SWIFT_AST_FUNCTION_REF_KIND_H

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ namespace swift {
9595
/// was not compiled with -enable-testing.
9696
bool EnableTestableAttrRequiresTestableModule = true;
9797

98+
/// Whether to implement SE-0111, the removal of argument labels in types.
99+
bool SuppressArgumentLabelsInTypes = false;
100+
98101
///
99102
/// Flags for developers
100103
///

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ def disable_testable_attr_requires_testable_module :
9494
Flag<["-"], "disable-testable-attr-requires-testable-module">,
9595
HelpText<"Disable checking of @testable">;
9696

97+
def suppress_argument_labels_in_types :
98+
Flag<["-"], "suppress-argument-labels-in-types">,
99+
HelpText<"SE-0111: Suppress argument labels in types">;
100+
97101
def enable_target_os_checking :
98102
Flag<["-"], "enable-target-os-checking">,
99103
HelpText<"Enable checking the target OS of serialized modules">;

lib/AST/ASTDumper.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,6 +1689,7 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
16891689
<< " decl=";
16901690
E->getDeclRef().dump(OS);
16911691
OS << E->getAccessSemantics();
1692+
OS << " function_ref=" << getFunctionRefKindStr(E->getFunctionRefKind());
16921693
OS << " specialized=" << (E->isSpecialized()? "yes" : "no");
16931694

16941695
for (auto TR : E->getGenericArgs()) {
@@ -1721,7 +1722,8 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
17211722
printCommon(E, "overloaded_decl_ref_expr")
17221723
<< " name=" << E->getDecls()[0]->getName()
17231724
<< " #decls=" << E->getDecls().size()
1724-
<< " specialized=" << (E->isSpecialized()? "yes" : "no");
1725+
<< " specialized=" << (E->isSpecialized()? "yes" : "no")
1726+
<< " function_ref=" << getFunctionRefKindStr(E->getFunctionRefKind());
17251727

17261728
for (ValueDecl *D : E->getDecls()) {
17271729
OS << '\n';
@@ -1733,7 +1735,8 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
17331735
void visitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *E) {
17341736
printCommon(E, "unresolved_decl_ref_expr")
17351737
<< " name=" << E->getName()
1736-
<< " specialized=" << (E->isSpecialized()? "yes" : "no") << ')';
1738+
<< " specialized=" << (E->isSpecialized()? "yes" : "no") << ')'
1739+
<< " function_ref=" << getFunctionRefKindStr(E->getFunctionRefKind());
17371740
}
17381741
void visitUnresolvedSpecializeExpr(UnresolvedSpecializeExpr *E) {
17391742
printCommon(E, "unresolved_specialize_expr") << '\n';

lib/AST/Expr.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@
3030
#include "llvm/ADT/Twine.h"
3131
using namespace swift;
3232

33+
StringRef swift::getFunctionRefKindStr(FunctionRefKind refKind) {
34+
switch (refKind) {
35+
case FunctionRefKind::Unapplied:
36+
return "unapplied";
37+
case FunctionRefKind::SingleApply:
38+
return "single";
39+
case FunctionRefKind::DoubleApply:
40+
return "double";
41+
case FunctionRefKind::Compound:
42+
return "compound";
43+
}
44+
}
45+
3346
//===----------------------------------------------------------------------===//
3447
// Expr methods.
3548
//===----------------------------------------------------------------------===//

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
792792
= A->getOption().matches(OPT_enable_testable_attr_requires_testable_module);
793793
}
794794

795+
Opts.SuppressArgumentLabelsInTypes |=
796+
Args.hasArg(OPT_suppress_argument_labels_in_types);
797+
795798
if (const Arg *A = Args.getLastArg(OPT_debug_constraints_attempt)) {
796799
unsigned attempt;
797800
if (StringRef(A->getValue()).getAsInteger(10, attempt)) {

lib/Sema/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ add_swift_library(swiftSema STATIC
2020
IterativeTypeChecker.cpp
2121
MiscDiagnostics.cpp
2222
NameBinding.cpp
23-
OverloadChoice.cpp
2423
PlaygroundTransform.cpp
2524
SourceLoader.cpp
2625
TypeCheckAttr.cpp

0 commit comments

Comments
 (0)