Skip to content

SE-0111 Work in progress: stripping argument labels from function references #3837

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
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
3 changes: 3 additions & 0 deletions include/swift/AST/DeclNameLoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ class DeclNameLoc {
/// Whether the location information is invalid.
bool isInvalid() const { return getBaseNameLoc().isInvalid(); }

/// Whether this was written as a compound name.
bool isCompound() const { return NumArgumentLabels > 0; }

/// Retrieve the location of the base name.
SourceLoc getBaseNameLoc() const {
return getSourceLocs()[BaseNameIndex];
Expand Down
146 changes: 121 additions & 25 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "swift/AST/CaptureInfo.h"
#include "swift/AST/ConcreteDeclRef.h"
#include "swift/AST/DeclNameLoc.h"
#include "swift/AST/FunctionRefKind.h"
#include "swift/AST/ProtocolConformanceRef.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/AST/TypeLoc.h"
Expand Down Expand Up @@ -53,7 +54,7 @@ namespace swift {
class PatternBindingDecl;
class ParameterList;
class EnumElementDecl;

enum class ExprKind : uint8_t {
#define EXPR(Id, Parent) Id,
#define EXPR_RANGE(Id, FirstId, LastId) \
Expand Down Expand Up @@ -114,7 +115,7 @@ enum class AccessSemantics : unsigned char {
/// polymorphism is expected.
Ordinary,
};

/// Expr - Base class for all expressions in swift.
class alignas(8) Expr {
Expr(const Expr&) = delete;
Expand Down Expand Up @@ -164,10 +165,21 @@ class alignas(8) Expr {
friend class DeclRefExpr;
unsigned : NumExprBits;
unsigned Semantics : 2; // an AccessSemantics
unsigned FunctionRefKind : 2;
};
enum { NumDeclRefExprBits = NumExprBits + 2 };
enum { NumDeclRefExprBits = NumExprBits + 4 };
static_assert(NumDeclRefExprBits <= 32, "fits in an unsigned");

class UnresolvedDeclRefExprBitfields {
friend class UnresolvedDeclRefExpr;
unsigned : NumExprBits;
unsigned DeclRefKind : 2;
unsigned IsSpecialized : 1;
unsigned FunctionRefKind : 2;
};
enum { NumUnresolvedDeclRefExprBits = NumExprBits + 5 };
static_assert(NumUnresolvedDeclRefExprBits <= 32, "fits in an unsigned");

class MemberRefExprBitfields {
friend class MemberRefExpr;
unsigned : NumExprBits;
Expand All @@ -193,6 +205,14 @@ class alignas(8) Expr {
enum { NumTupleExprBits = NumExprBits + 3 };
static_assert(NumTupleExprBits <= 32, "fits in an unsigned");

class UnresolvedDotExprBitfields {
friend class UnresolvedDotExpr;
unsigned : NumExprBits;
unsigned FunctionRefKind : 2;
};
enum { NumUnresolvedDotExprExprBits = NumExprBits + 2 };
static_assert(NumUnresolvedDotExprExprBits <= 32, "fits in an unsigned");

class SubscriptExprBitfields {
friend class SubscriptExpr;
unsigned : NumExprBits;
Expand Down Expand Up @@ -242,10 +262,19 @@ class alignas(8) Expr {
class OverloadSetRefExprBitfields {
friend class OverloadSetRefExpr;
unsigned : NumExprBits;
unsigned FunctionRefKind : 2;
};
enum { NumOverloadSetRefExprBits = NumExprBits };
enum { NumOverloadSetRefExprBits = NumExprBits + 2};
static_assert(NumOverloadSetRefExprBits <= 32, "fits in an unsigned");

class OverloadedDeclRefExprBitfields {
friend class OverloadedDeclRefExpr;
unsigned : NumOverloadSetRefExprBits;
unsigned IsSpecialized : 1;
};
enum { NumOverloadedDeclRefExprBits = NumOverloadSetRefExprBits + 1 };
static_assert(NumOverloadedDeclRefExprBits <= 32, "fits in an unsigned");

class BooleanLiteralExprBitfields {
friend class BooleanLiteralExpr;
unsigned : NumLiteralExprBits;
Expand Down Expand Up @@ -398,12 +427,15 @@ class alignas(8) Expr {
NumberLiteralExprBitfields NumberLiteralExprBits;
StringLiteralExprBitfields StringLiteralExprBits;
DeclRefExprBitfields DeclRefExprBits;
UnresolvedDeclRefExprBitfields UnresolvedDeclRefExprBits;
TupleExprBitfields TupleExprBits;
MemberRefExprBitfields MemberRefExprBits;
UnresolvedDotExprBitfields UnresolvedDotExprBits;
SubscriptExprBitfields SubscriptExprBits;
DynamicSubscriptExprBitfields DynamicSubscriptExprBits;
UnresolvedMemberExprBitfields UnresolvedMemberExprBits;
OverloadSetRefExprBitfields OverloadSetRefExprBits;
OverloadedDeclRefExprBitfields OverloadedDeclRefExprBits;
BooleanLiteralExprBitfields BooleanLiteralExprBits;
MagicIdentifierLiteralExprBitfields MagicIdentifierLiteralExprBits;
ObjectLiteralExprBitfields ObjectLiteralExprBits;
Expand Down Expand Up @@ -1212,6 +1244,9 @@ class DeclRefExpr : public Expr {
Type Ty = Type())
: Expr(ExprKind::DeclRef, Implicit, Ty), DOrSpecialized(D), Loc(Loc) {
DeclRefExprBits.Semantics = (unsigned) semantics;
DeclRefExprBits.FunctionRefKind =
static_cast<unsigned>(Loc.isCompound() ? FunctionRefKind::Compound
: FunctionRefKind::Unapplied);
}

/// Retrieve the declaration to which this expression refers.
Expand Down Expand Up @@ -1254,6 +1289,16 @@ class DeclRefExpr : public Expr {
SourceLoc getLoc() const { return Loc.getBaseNameLoc(); }
DeclNameLoc getNameLoc() const { return Loc; }

/// Retrieve the kind of function reference.
FunctionRefKind getFunctionRefKind() const {
return static_cast<FunctionRefKind>(DeclRefExprBits.FunctionRefKind);
}

/// Set the kind of function reference.
void setFunctionRefKind(FunctionRefKind refKind) {
DeclRefExprBits.FunctionRefKind = static_cast<unsigned>(refKind);
}

static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DeclRef;
}
Expand Down Expand Up @@ -1364,9 +1409,12 @@ class OverloadSetRefExpr : public Expr {
ArrayRef<ValueDecl*> Decls;

protected:
OverloadSetRefExpr(ExprKind Kind, ArrayRef<ValueDecl*> decls, bool Implicit,
Type Ty)
: Expr(Kind, Implicit, Ty), Decls(decls) {}
OverloadSetRefExpr(ExprKind Kind, ArrayRef<ValueDecl*> decls,
FunctionRefKind functionRefKind, bool Implicit, Type Ty)
: Expr(Kind, Implicit, Ty), Decls(decls) {
OverloadSetRefExprBits.FunctionRefKind =
static_cast<unsigned>(functionRefKind);
}

public:
ArrayRef<ValueDecl*> getDecls() const { return Decls; }
Expand All @@ -1380,6 +1428,17 @@ class OverloadSetRefExpr : public Expr {
/// concrete base object (which is not a metatype).
bool hasBaseObject() const;

/// Retrieve the kind of function reference.
FunctionRefKind getFunctionRefKind() const {
return static_cast<FunctionRefKind>(
OverloadSetRefExprBits.FunctionRefKind);
}

/// Set the kind of function reference.
void setFunctionRefKind(FunctionRefKind refKind) {
OverloadSetRefExprBits.FunctionRefKind = static_cast<unsigned>(refKind);
}

static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_OverloadSetRefExpr &&
E->getKind() <= ExprKind::Last_OverloadSetRefExpr;
Expand All @@ -1388,26 +1447,30 @@ class OverloadSetRefExpr : public Expr {

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

public:
OverloadedDeclRefExpr(ArrayRef<ValueDecl*> Decls, DeclNameLoc Loc,
bool isSpecialized,
FunctionRefKind functionRefKind,
bool Implicit, Type Ty = Type())
: OverloadSetRefExpr(ExprKind::OverloadedDeclRef, Decls, Implicit, Ty),
Loc(Loc) { }
: OverloadSetRefExpr(ExprKind::OverloadedDeclRef, Decls, functionRefKind,
Implicit, Ty),
Loc(Loc) {
OverloadedDeclRefExprBits.IsSpecialized = isSpecialized;
}

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

void setSpecialized(bool specialized) { IsSpecialized = specialized; }

/// \brief Determine whether this declaration reference was immediately
/// specialized by <...>.
bool isSpecialized() const { return IsSpecialized; }

bool isSpecialized() const {
return OverloadedDeclRefExprBits.IsSpecialized;
}

static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OverloadedDeclRef;
}
Expand All @@ -1421,29 +1484,48 @@ class OverloadedDeclRefExpr : public OverloadSetRefExpr {
class UnresolvedDeclRefExpr : public Expr {
DeclName Name;
DeclNameLoc Loc;
DeclRefKind RefKind;
bool IsSpecialized = false;

public:
UnresolvedDeclRefExpr(DeclName name, DeclRefKind refKind, DeclNameLoc loc)
: Expr(ExprKind::UnresolvedDeclRef, /*Implicit=*/loc.isInvalid()),
Name(name), Loc(loc), RefKind(refKind) {
: Expr(ExprKind::UnresolvedDeclRef, /*Implicit=*/loc.isInvalid()),
Name(name), Loc(loc) {
UnresolvedDeclRefExprBits.DeclRefKind = static_cast<unsigned>(refKind);
UnresolvedDeclRefExprBits.IsSpecialized = false;
UnresolvedDeclRefExprBits.FunctionRefKind =
static_cast<unsigned>(Loc.isCompound() ? FunctionRefKind::Compound
: FunctionRefKind::Unapplied);
}

bool hasName() const { return static_cast<bool>(Name); }
DeclName getName() const { return Name; }
DeclRefKind getRefKind() const { return RefKind; }

void setSpecialized(bool specialized) { IsSpecialized = specialized; }
DeclRefKind getRefKind() const {
return static_cast<DeclRefKind>(UnresolvedDeclRefExprBits.DeclRefKind);
}

void setSpecialized(bool specialized) {
UnresolvedDeclRefExprBits.IsSpecialized = specialized;
}

/// \brief Determine whether this declaration reference was immediately
/// specialized by <...>.
bool isSpecialized() const { return IsSpecialized; }
bool isSpecialized() const { return UnresolvedDeclRefExprBits.IsSpecialized; }

/// Retrieve the kind of function reference.
FunctionRefKind getFunctionRefKind() const {
return static_cast<FunctionRefKind>(
UnresolvedDeclRefExprBits.FunctionRefKind);
}

/// Set the kind of function reference.
void setFunctionRefKind(FunctionRefKind refKind) {
UnresolvedDeclRefExprBits.FunctionRefKind = static_cast<unsigned>(refKind);
}

DeclNameLoc getNameLoc() const { return Loc; }

SourceRange getSourceRange() const { return Loc.getSourceRange(); }

static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedDeclRef;
}
Expand Down Expand Up @@ -2246,8 +2328,12 @@ class UnresolvedDotExpr : public Expr {
public:
UnresolvedDotExpr(Expr *subexpr, SourceLoc dotloc, DeclName name,
DeclNameLoc nameloc, bool Implicit)
: Expr(ExprKind::UnresolvedDot, Implicit), SubExpr(subexpr), DotLoc(dotloc),
NameLoc(nameloc), Name(name) {}
: Expr(ExprKind::UnresolvedDot, Implicit), SubExpr(subexpr), DotLoc(dotloc),
NameLoc(nameloc), Name(name) {
UnresolvedDotExprBits.FunctionRefKind =
static_cast<unsigned>(NameLoc.isCompound() ? FunctionRefKind::Compound
: FunctionRefKind::Unapplied);
}

SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }

Expand All @@ -2266,6 +2352,16 @@ class UnresolvedDotExpr : public Expr {
DeclName getName() const { return Name; }
DeclNameLoc getNameLoc() const { return NameLoc; }

/// Retrieve the kind of function reference.
FunctionRefKind getFunctionRefKind() const {
return static_cast<FunctionRefKind>(UnresolvedDotExprBits.FunctionRefKind);
}

/// Set the kind of function reference.
void setFunctionRefKind(FunctionRefKind refKind) {
UnresolvedDotExprBits.FunctionRefKind = static_cast<unsigned>(refKind);
}

static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedDot;
}
Expand Down
50 changes: 50 additions & 0 deletions include/swift/AST/FunctionRefKind.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//===--- FunctionRefKind.h - Function reference kind ------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the FunctionRefKind enum, which is used to describe how
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_AST_FUNCTION_REF_KIND_H
#define SWIFT_AST_FUNCTION_REF_KIND_H

namespace swift {

/// Describes how a function is referenced within an expression node,
/// which dictates whether argument labels are part of the resulting
/// function type or not.
///
/// How a function is referenced comes down to how it was spelled in
/// the source code, e.g., was it called in the source code and was it
/// spelled as a compound name.
enum class FunctionRefKind : unsigned {
/// The function was referenced using a bare function name (e.g.,
/// 'f') and not directly called.
Unapplied,
/// The function was referenced using a bare function name and was
/// directly applied once, e.g., "f(a: 1, b: 2)".
SingleApply,
/// The function was referenced using a bare function name and was
/// directly applied two or more times, e.g., "g(x)(y)".
DoubleApply,
/// The function was referenced using a compound function name,
/// e.g., "f(a:b:)".
Compound,
};

/// Produce a string describing a function reference kind, for
/// debugging purposes.
StringRef getFunctionRefKindStr(FunctionRefKind refKind);

}

#endif // SWIFT_AST_FUNCTION_REF_KIND_H
3 changes: 3 additions & 0 deletions include/swift/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ namespace swift {
/// was not compiled with -enable-testing.
bool EnableTestableAttrRequiresTestableModule = true;

/// Whether to implement SE-0111, the removal of argument labels in types.
bool SuppressArgumentLabelsInTypes = false;

///
/// Flags for developers
///
Expand Down
4 changes: 4 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ def disable_testable_attr_requires_testable_module :
Flag<["-"], "disable-testable-attr-requires-testable-module">,
HelpText<"Disable checking of @testable">;

def suppress_argument_labels_in_types :
Flag<["-"], "suppress-argument-labels-in-types">,
HelpText<"SE-0111: Suppress argument labels in types">;

def enable_target_os_checking :
Flag<["-"], "enable-target-os-checking">,
HelpText<"Enable checking the target OS of serialized modules">;
Expand Down
Loading