Skip to content

[AST/Sema] Associate @autoclosure flag with parameter declaration #20152

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 17 commits into from
Nov 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
4c1885b
[AST] Register `@autoclosure` as parameter decl flag
xedin Oct 26, 2018
0857611
[Serialization] Add `@autoclosure` to parameter decl serialization fo…
xedin Oct 26, 2018
53417f4
[AST] Propagate `@autoclosure` flag to parameter decl and type flags
xedin Oct 28, 2018
d9504ef
[TypeChecker] Add `typeCheckParameterDefault` method
xedin Oct 28, 2018
f462521
[ConstraintSystem] Refactor arg/param matching to handle autoclosures
xedin Oct 30, 2018
6224d12
[ConstraintSystem] Remove now redundant `@autoclosure` checking
xedin Oct 31, 2018
b3f8625
[CodeCompletion] Add `isAutoClosure` flag to parameter builder
xedin Oct 31, 2018
6b62ac8
[CSDiag] Switch expression diagnostics to check `@autoclosure` from p…
xedin Nov 1, 2018
a1df238
Associate `@autoclosure` only with parameter types
xedin Nov 1, 2018
d113b4a
[CSApply] Refactor `ExprRewriter` to handle `@autoclosure` from param…
xedin Nov 1, 2018
bce1ba5
[AST] Remove `@autoclosure` flag from function type `ExtInfo`
xedin Nov 2, 2018
ed84f18
[AST] NFC: Remove a FIXME related to ParamDecl::IsAutoClosure field
xedin Nov 2, 2018
6c8513f
[ConstraintSystem] Test @autoclosure behavior in Swift < 5 compatibil…
xedin Nov 2, 2018
e50537d
[CSApply] Handle @autoclosure arg/param conversions in Swift versions…
xedin Nov 4, 2018
3ffda7e
[ASTManger] Refactor parameter mangling code a bit based on feedback
xedin Nov 5, 2018
c532583
[TypeChecker] NFC: Delete rudimentary `AutoClosureListener::isInDefau…
xedin Nov 6, 2018
7bd2688
[Overlay] Fix XCTest overlay to avoid passing autoclosures through
xedin Nov 7, 2018
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
2 changes: 1 addition & 1 deletion include/swift/AST/ASTMangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ class ASTMangler : public Mangler {
void appendAnyGenericType(const GenericTypeDecl *decl);

void appendFunction(AnyFunctionType *fn, bool isFunctionMangling = false);
void appendFunctionType(AnyFunctionType *fn);
void appendFunctionType(AnyFunctionType *fn, bool isAutoClosure = false);

void appendFunctionSignature(AnyFunctionType *fn);

Expand Down
23 changes: 11 additions & 12 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4849,7 +4849,10 @@ class ParamDecl : public VarDecl {

/// The default value, if any, along with whether this is varargs.
llvm::PointerIntPair<StoredDefaultArgument *, 1> DefaultValueAndIsVariadic;


/// `@autoclosure` flag associated with this parameter.
bool IsAutoClosure = false;

public:
ParamDecl(VarDecl::Specifier specifier,
SourceLoc specifierLoc, SourceLoc argumentNameLoc,
Expand Down Expand Up @@ -4933,7 +4936,11 @@ class ParamDecl : public VarDecl {
/// Whether or not this parameter is varargs.
bool isVariadic() const { return DefaultValueAndIsVariadic.getInt(); }
void setVariadic(bool value = true) {DefaultValueAndIsVariadic.setInt(value);}


/// Whether or not this parameter is marked with `@autoclosure`.
bool isAutoClosure() const { return IsAutoClosure; }
void setAutoClosure(bool value = true) { IsAutoClosure = value; }

/// Remove the type of this varargs element designator, without the array
/// type wrapping it. A parameter like "Int..." will have formal parameter
/// type of "[Int]" and this returns "Int".
Expand Down Expand Up @@ -6835,16 +6842,8 @@ inline EnumElementDecl *EnumDecl::getUniqueElement(bool hasValue) const {
return result;
}

/// Determine the default argument kind and type for the given argument index
/// in this declaration, which must be a function or constructor.
///
/// \param Index The index of the argument for which we are querying the
/// default argument.
///
/// \returns the default argument kind and, if there is a default argument,
/// the type of the corresponding parameter.
std::pair<DefaultArgumentKind, Type>
getDefaultArgumentInfo(ValueDecl *source, unsigned Index);
/// Retrieve parameter declaration from the given source at given index.
const ParamDecl *getParameterAt(ValueDecl *source, unsigned index);

/// Display Decl subclasses.
void simple_display(llvm::raw_ostream &out, const Decl *decl);
Expand Down
38 changes: 11 additions & 27 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ class alignas(1 << TypeAlignInBits) TypeBase {
}

protected:
enum { NumAFTExtInfoBits = 7 };
enum { NumAFTExtInfoBits = 6 };
enum { NumSILExtInfoBits = 6 };
union { uint64_t OpaqueBits;

Expand Down Expand Up @@ -1743,7 +1743,8 @@ class ParameterTypeFlags {

/// Create one from what's present in the parameter type
inline static ParameterTypeFlags
fromParameterType(Type paramTy, bool isVariadic, ValueOwnership ownership);
fromParameterType(Type paramTy, bool isVariadic, bool isAutoClosure,
ValueOwnership ownership);

bool isNone() const { return !value; }
bool isVariadic() const { return value.contains(Variadic); }
Expand Down Expand Up @@ -2835,15 +2836,14 @@ class AnyFunctionType : public TypeBase {
// If bits are added or removed, then TypeBase::AnyFunctionTypeBits
// and NumMaskBits must be updated, and they must match.
//
// |representation|isAutoClosure|noEscape|throws|
// | 0 .. 3 | 4 | 5 | 6 |
// |representation|noEscape|throws|
// | 0 .. 3 | 4 | 5 |
//
enum : unsigned {
RepresentationMask = 0xF << 0,
AutoClosureMask = 1 << 4,
NoEscapeMask = 1 << 5,
ThrowsMask = 1 << 6,
NumMaskBits = 7
NoEscapeMask = 1 << 4,
ThrowsMask = 1 << 5,
NumMaskBits = 6
};

unsigned Bits; // Naturally sized for speed.
Expand All @@ -2865,14 +2865,12 @@ class AnyFunctionType : public TypeBase {

// Constructor with no defaults.
ExtInfo(Representation Rep,
bool IsAutoClosure, bool IsNoEscape,
bool IsNoEscape,
bool Throws)
: ExtInfo(Rep, Throws) {
Bits |= (IsAutoClosure ? AutoClosureMask : 0);
Bits |= (IsNoEscape ? NoEscapeMask : 0);
}

bool isAutoClosure() const { return Bits & AutoClosureMask; }
bool isNoEscape() const { return Bits & NoEscapeMask; }
bool throws() const { return Bits & ThrowsMask; }
Representation getRepresentation() const {
Expand Down Expand Up @@ -2925,13 +2923,6 @@ class AnyFunctionType : public TypeBase {
| (unsigned)Rep);
}
LLVM_NODISCARD
ExtInfo withIsAutoClosure(bool IsAutoClosure = true) const {
if (IsAutoClosure)
return ExtInfo(Bits | AutoClosureMask);
else
return ExtInfo(Bits & ~AutoClosureMask);
}
LLVM_NODISCARD
ExtInfo withNoEscape(bool NoEscape = true) const {
if (NoEscape)
return ExtInfo(Bits | NoEscapeMask);
Expand Down Expand Up @@ -3028,12 +3019,6 @@ class AnyFunctionType : public TypeBase {
Representation getRepresentation() const {
return getExtInfo().getRepresentation();
}

/// \brief True if this type allows an implicit conversion from a function
/// argument expression of type T to a function of type () -> T.
bool isAutoClosure() const {
return getExtInfo().isAutoClosure();
}

/// \brief True if the parameter declaration it is attached to is guaranteed
/// to not persist the closure for longer than the duration of the call.
Expand Down Expand Up @@ -5325,9 +5310,8 @@ inline TupleTypeElt TupleTypeElt::getWithType(Type T) const {
/// Create one from what's present in the parameter decl and type
inline ParameterTypeFlags
ParameterTypeFlags::fromParameterType(Type paramTy, bool isVariadic,
bool isAutoClosure,
ValueOwnership ownership) {
bool autoclosure = paramTy->is<AnyFunctionType>() &&
paramTy->castTo<AnyFunctionType>()->isAutoClosure();
bool escaping = paramTy->is<AnyFunctionType>() &&
!paramTy->castTo<AnyFunctionType>()->isNoEscape();
// FIXME(Remove InOut): The last caller that needs this is argument
Expand All @@ -5339,7 +5323,7 @@ ParameterTypeFlags::fromParameterType(Type paramTy, bool isVariadic,
ownership == ValueOwnership::InOut);
ownership = ValueOwnership::InOut;
}
return {isVariadic, autoclosure, escaping, ownership};
return {isVariadic, isAutoClosure, escaping, ownership};
}

inline const Type *BoundGenericType::getTrailingObjectsPointer() const {
Expand Down
4 changes: 2 additions & 2 deletions include/swift/Serialization/ModuleFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
/// Don't worry about adhering to the 80-column limit for this line.
const uint16_t SWIFTMODULE_VERSION_MINOR = 465; // Last change: Remove owning addressors
const uint16_t SWIFTMODULE_VERSION_MINOR = 466; // Last change: add isAutoClosure flag to param

using DeclIDField = BCFixed<31>;

Expand Down Expand Up @@ -737,7 +737,6 @@ namespace decls_block {
FUNCTION_TYPE,
TypeIDField, // output
FunctionTypeRepresentationField, // representation
BCFixed<1>, // auto-closure?
BCFixed<1>, // noescape?
BCFixed<1> // throws?

Expand Down Expand Up @@ -1024,6 +1023,7 @@ namespace decls_block {
VarDeclSpecifierField, // specifier
TypeIDField, // interface type
BCFixed<1>, // isVariadic?
BCFixed<1>, // isAutoClosure?
DefaultArgumentField, // default argument kind
BCBlob // default argument text
>;
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3722,7 +3722,7 @@ void AnyFunctionType::decomposeInput(
default:
result.emplace_back(type->getInOutObjectType(), Identifier(),
ParameterTypeFlags::fromParameterType(
type, false, ValueOwnership::Default));
type, false, false, ValueOwnership::Default));
return;
}
}
Expand Down
4 changes: 3 additions & 1 deletion lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,9 @@ namespace {
if (P->isVariadic())
OS << " variadic";

if (P->isAutoClosure())
OS << " autoclosure";

if (P->getDefaultArgumentKind() != DefaultArgumentKind::None)
printField("default_arg",
getDefaultArgumentKindString(P->getDefaultArgumentKind()));
Expand Down Expand Up @@ -3436,7 +3439,6 @@ namespace {
printField("representation",
getSILFunctionTypeRepresentationString(representation));

printFlag(T->isAutoClosure(), "autoclosure");
printFlag(!T->isNoEscape(), "escaping");
printFlag(T->throws(), "throws");

Expand Down
10 changes: 7 additions & 3 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1693,7 +1693,7 @@ void ASTMangler::appendFunction(AnyFunctionType *fn, bool isFunctionMangling) {
}
}

void ASTMangler::appendFunctionType(AnyFunctionType *fn) {
void ASTMangler::appendFunctionType(AnyFunctionType *fn, bool isAutoClosure) {
assert((DWARFMangling || fn->isCanonical()) &&
"expecting canonical types when not mangling for the debugger");

Expand All @@ -1715,7 +1715,7 @@ void ASTMangler::appendFunctionType(AnyFunctionType *fn) {
case AnyFunctionType::Representation::Thin:
return appendOperator("Xf");
case AnyFunctionType::Representation::Swift:
if (fn->isAutoClosure()) {
if (isAutoClosure) {
if (fn->isNoEscape())
return appendOperator("XK");
else
Expand Down Expand Up @@ -1799,7 +1799,11 @@ void ASTMangler::appendTypeList(Type listTy) {

void ASTMangler::appendTypeListElement(Identifier name, Type elementType,
ParameterTypeFlags flags) {
appendType(elementType);
if (auto *fnType = elementType->getAs<FunctionType>())
appendFunctionType(fnType, flags.isAutoClosure());
else
appendType(elementType);

switch (flags.getValueOwnership()) {
case ValueOwnership::Default:
/* nothing */
Expand Down
10 changes: 4 additions & 6 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2040,7 +2040,6 @@ mapSignatureExtInfo(AnyFunctionType::ExtInfo info,
return AnyFunctionType::ExtInfo();
return AnyFunctionType::ExtInfo()
.withRepresentation(info.getRepresentation())
.withIsAutoClosure(info.isAutoClosure())
.withThrows(info.throws());
}

Expand Down Expand Up @@ -4802,7 +4801,8 @@ ParamDecl::ParamDecl(ParamDecl *PD, bool withTypes)
ArgumentName(PD->getArgumentName()),
ArgumentNameLoc(PD->getArgumentNameLoc()),
SpecifierLoc(PD->getSpecifierLoc()),
DefaultValueAndIsVariadic(nullptr, PD->DefaultValueAndIsVariadic.getInt()) {
DefaultValueAndIsVariadic(nullptr, PD->DefaultValueAndIsVariadic.getInt()),
IsAutoClosure(PD->isAutoClosure()) {
Bits.ParamDecl.IsTypeLocImplicit = PD->Bits.ParamDecl.IsTypeLocImplicit;
Bits.ParamDecl.defaultArgumentKind = PD->Bits.ParamDecl.defaultArgumentKind;
typeLoc = PD->getTypeLoc().clone(PD->getASTContext());
Expand Down Expand Up @@ -5107,17 +5107,15 @@ DeclName AbstractFunctionDecl::getEffectiveFullName() const {
return DeclName();
}

std::pair<DefaultArgumentKind, Type>
swift::getDefaultArgumentInfo(ValueDecl *source, unsigned Index) {
const ParamDecl *swift::getParameterAt(ValueDecl *source, unsigned index) {
const ParameterList *paramList;
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(source)) {
paramList = AFD->getParameters();
} else {
paramList = cast<EnumElementDecl>(source)->getParameterList();
}

auto param = paramList->get(Index);
return { param->getDefaultArgumentKind(), param->getInterfaceType() };
return paramList->get(index);
}

Type AbstractFunctionDecl::getMethodInterfaceType() const {
Expand Down
4 changes: 3 additions & 1 deletion lib/AST/Parameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ void ParameterList::getParams(
type = ParamDecl::getVarargBaseTy(type);

auto label = P->getArgumentName();
auto flags = ParameterTypeFlags::fromParameterType(type, P->isVariadic(),
auto flags = ParameterTypeFlags::fromParameterType(type,
P->isVariadic(),
P->isAutoClosure(),
P->getValueOwnership());
params.emplace_back(type, label, flags);
}
Expand Down
36 changes: 19 additions & 17 deletions lib/IDE/CodeCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2172,7 +2172,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {

Builder.addCallParameter(param->getArgumentName(), type,
param->isVariadic(), /*Outermost*/ true,
param->isInOut(), isIUO);
param->isInOut(), isIUO, param->isAutoClosure());
}
}

Expand Down Expand Up @@ -2270,12 +2270,12 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
auto isIUO =
PD->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
Builder.addCallParameter(argName, bodyName, ParamType,
Param.isVariadic(), /*TopLevel*/true,
Param.isInOut(), isIUO);
} else {
Builder.addCallParameter(Param.getLabel(), ParamType,
Param.isVariadic(), /*TopLevel*/ true,
Param.isInOut(), /*isIUO*/ false);
Param.isInOut(), isIUO, Param.isAutoClosure());
} else {
Builder.addCallParameter(
Param.getLabel(), ParamType, Param.isVariadic(), /*TopLevel*/ true,
Param.isInOut(), /*isIUO*/ false, Param.isAutoClosure());
}
modifiedBuilder = true;
NeedComma = true;
Expand Down Expand Up @@ -2490,7 +2490,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
Builder.addCallParameter(Ctx.Id_self, SelfParam.getPlainType(),
/*IsVarArg*/ false, /*TopLevel*/ true,
SelfParam.isInOut(),
/*isIUO*/ false);
/*isIUO*/ false, /*isAutoClosure*/ false);
Builder.addRightParen();
} else if (trivialTrailingClosure) {
Builder.addBraceStmtWithCursor(" { code }");
Expand Down Expand Up @@ -3336,7 +3336,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
assert(RHSType && resultType);
builder.addCallParameter(Identifier(), Identifier(), RHSType,
/*IsVarArg*/ false, /*TopLevel*/ true,
/*IsInOut*/ false, /*isIUO*/ false);
/*IsInOut*/ false, /*isIUO*/ false,
/*isAutoClosure*/ false);
addTypeAnnotation(builder, resultType);
}

Expand All @@ -3359,7 +3360,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
builder.addWhitespace(" ");
if (RHSType)
builder.addCallParameter(Identifier(), Identifier(), RHSType, false, true,
/*IsInOut*/ false, /*isIUO*/ false);
/*IsInOut*/ false, /*isIUO*/ false,
/*isAutoClosure*/ false);
if (resultType)
addTypeAnnotation(builder, resultType);
}
Expand Down Expand Up @@ -3648,19 +3650,19 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
builder.addLeftParen();
builder.addCallParameter(context.getIdentifier("red"), floatType, false,
true, /*IsInOut*/ false,
/*isIUO*/ false);
/*isIUO*/ false, /*isAutoClosure*/ false);
builder.addComma();
builder.addCallParameter(context.getIdentifier("green"), floatType, false,
true, /*IsInOut*/ false,
/*isIUO*/ false);
true, /*IsInOut*/ false, /*isIUO*/ false,
/*isAutoClosure*/ false);
builder.addComma();
builder.addCallParameter(context.getIdentifier("blue"), floatType, false,
true, /*IsInOut*/ false,
/*isIUO*/ false);
true, /*IsInOut*/ false, /*isIUO*/ false,
/*isAutoClosure*/ false);
builder.addComma();
builder.addCallParameter(context.getIdentifier("alpha"), floatType, false,
true, /*IsInOut*/ false,
/*isIUO*/ false);
true, /*IsInOut*/ false, /*isIUO*/ false,
/*isAutoClosure*/ false);
builder.addRightParen();
});

Expand All @@ -3670,7 +3672,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
builder.addLeftParen();
builder.addCallParameter(context.getIdentifier("resourceName"),
stringType, false, true, /*IsInOut*/ false,
/*isIUO*/ false);
/*isIUO*/ false, /*isAutoClosure*/ false);
builder.addRightParen();
});

Expand Down
Loading