Skip to content

Commit 239c5d3

Browse files
authored
Merge pull request #4931 from milseman/3_0_escaping_printing_fix_clean
[3.0] Fix @escaping printing (from #4905)
2 parents 51efc38 + 63278b1 commit 239c5d3

31 files changed

+1603
-1334
lines changed

include/swift/AST/PrintOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,9 @@ struct PrintOptions {
244244
/// protocol requirements.
245245
bool SkipOverrides = false;
246246

247+
/// Whether to skip parameter type attributes
248+
bool SkipParameterTypeAttributes = false;
249+
247250
/// Whether to print a long attribute like '\@available' on a separate line
248251
/// from the declaration or other attributes.
249252
bool PrintLongAttrsOnSeparateLines = false;

include/swift/AST/Types.h

Lines changed: 124 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,22 +1276,79 @@ class NameAliasType : public TypeBase {
12761276
}
12771277
};
12781278

1279+
// TODO: As part of AST modernization, replace with a proper
1280+
// 'ParameterTypeElt' or similar, and have FunctionTypes only have a list
1281+
// of 'ParameterTypeElt's. Then, this information can be removed from
1282+
// TupleTypeElt.
1283+
//
1284+
/// Provide parameter type relevant flags, i.e. variadic, autoclosure, and
1285+
/// escaping.
1286+
class ParameterTypeFlags {
1287+
enum ParameterFlags : uint8_t {
1288+
None = 0,
1289+
Variadic = 1 << 0,
1290+
AutoClosure = 1 << 1,
1291+
Escaping = 1 << 2,
1292+
1293+
NumBits = 3
1294+
};
1295+
OptionSet<ParameterFlags> value;
1296+
static_assert(NumBits < 8*sizeof(value), "overflowed");
1297+
1298+
ParameterTypeFlags(OptionSet<ParameterFlags, uint8_t> val) : value(val) {}
1299+
1300+
public:
1301+
ParameterTypeFlags() = default;
1302+
1303+
ParameterTypeFlags(bool variadic, bool autoclosure, bool escaping)
1304+
: value((variadic ? Variadic : 0) |
1305+
(autoclosure ? AutoClosure : 0) |
1306+
(escaping ? Escaping : 0)) {}
1307+
1308+
/// Create one from what's present in the parameter type
1309+
inline static ParameterTypeFlags fromParameterType(Type paramTy,
1310+
bool isVariadic);
1311+
1312+
bool isNone() const { return !value; }
1313+
bool isVariadic() const { return value.contains(Variadic); }
1314+
bool isAutoClosure() const { return value.contains(AutoClosure); }
1315+
bool isEscaping() const { return value.contains(Escaping); }
1316+
1317+
ParameterTypeFlags withEscaping(bool escaping) const {
1318+
return ParameterTypeFlags(escaping ? value | ParameterTypeFlags::Escaping
1319+
: value - ParameterTypeFlags::Escaping);
1320+
}
1321+
1322+
bool operator ==(const ParameterTypeFlags &other) const {
1323+
return value.toRaw() == other.value.toRaw();
1324+
}
1325+
1326+
uint8_t toRaw() const { return value.toRaw(); }
1327+
};
1328+
12791329
/// ParenType - A paren type is a type that's been written in parentheses.
12801330
class ParenType : public TypeBase {
12811331
Type UnderlyingType;
1332+
ParameterTypeFlags parameterFlags;
12821333

12831334
friend class ASTContext;
1284-
ParenType(Type UnderlyingType, RecursiveTypeProperties properties)
1285-
: TypeBase(TypeKind::Paren, nullptr, properties),
1286-
UnderlyingType(UnderlyingType) {}
1335+
ParenType(Type UnderlyingType, RecursiveTypeProperties properties,
1336+
ParameterTypeFlags flags)
1337+
: TypeBase(TypeKind::Paren, nullptr, properties),
1338+
UnderlyingType(UnderlyingType), parameterFlags(flags) {}
1339+
12871340
public:
12881341
Type getUnderlyingType() const { return UnderlyingType; }
12891342

1290-
static ParenType *get(const ASTContext &C, Type underlying);
1291-
1343+
static ParenType *get(const ASTContext &C, Type underlying,
1344+
ParameterTypeFlags flags = {});
1345+
12921346
/// Remove one level of top-level sugar from this type.
12931347
TypeBase *getSinglyDesugaredType();
12941348

1349+
/// Get the parameter flags
1350+
ParameterTypeFlags getParameterFlags() const { return parameterFlags; }
1351+
12951352
// Implement isa/cast/dyncast/etc.
12961353
static bool classof(const TypeBase *T) {
12971354
return T->getKind() == TypeKind::Paren;
@@ -1300,33 +1357,45 @@ class ParenType : public TypeBase {
13001357

13011358
/// TupleTypeElt - This represents a single element of a tuple.
13021359
class TupleTypeElt {
1303-
/// An optional name for the field, along with a bit indicating whether it
1304-
/// is variadic.
1305-
llvm::PointerIntPair<Identifier, 1, bool> NameAndVariadic;
1360+
/// An optional name for the field.
1361+
Identifier Name;
13061362

13071363
/// \brief This is the type of the field.
13081364
Type ElementType;
13091365

1366+
/// Flags that are specific to and relevant for parameter types
1367+
ParameterTypeFlags Flags;
1368+
13101369
friend class TupleType;
13111370

13121371
public:
13131372
TupleTypeElt() = default;
1314-
inline /*implicit*/ TupleTypeElt(Type ty,
1315-
Identifier name = Identifier(),
1316-
bool isVariadic = false);
1373+
inline /*implicit*/ TupleTypeElt(Type ty, Identifier name,
1374+
bool isVariadic, bool isAutoClosure,
1375+
bool isEscaping);
1376+
1377+
TupleTypeElt(Type ty, Identifier name = Identifier(),
1378+
ParameterTypeFlags PTFlags = {})
1379+
: Name(name), ElementType(ty), Flags(PTFlags) {}
13171380

13181381
/*implicit*/ TupleTypeElt(TypeBase *Ty)
1319-
: NameAndVariadic(Identifier(), false), ElementType(Ty) { }
1382+
: Name(Identifier()), ElementType(Ty), Flags() { }
13201383

1321-
bool hasName() const { return !NameAndVariadic.getPointer().empty(); }
1322-
Identifier getName() const { return NameAndVariadic.getPointer(); }
1384+
bool hasName() const { return !Name.empty(); }
1385+
Identifier getName() const { return Name; }
13231386

13241387
Type getType() const { return ElementType.getPointer(); }
13251388

1389+
ParameterTypeFlags getParameterFlags() const { return Flags; }
1390+
13261391
/// Determine whether this field is variadic.
1327-
bool isVararg() const {
1328-
return NameAndVariadic.getInt();
1329-
}
1392+
bool isVararg() const { return Flags.isVariadic(); }
1393+
1394+
/// Determine whether this field is an autoclosure parameter closure.
1395+
bool isAutoClosure() const { return Flags.isAutoClosure(); }
1396+
1397+
/// Determine whether this field is an escaping parameter closure.
1398+
bool isEscaping() const { return Flags.isEscaping(); }
13301399

13311400
static inline Type getVarargBaseTy(Type VarArgT);
13321401

@@ -1339,8 +1408,16 @@ class TupleTypeElt {
13391408

13401409
/// Retrieve a copy of this tuple type element with the type replaced.
13411410
TupleTypeElt getWithType(Type T) const {
1342-
return TupleTypeElt(T, getName(), isVararg());
1411+
return TupleTypeElt(T, getName(), getParameterFlags());
13431412
}
1413+
1414+
/// Retrieve a copy of this tuple type element with the name replaced.
1415+
TupleTypeElt getWithName(Identifier name) const {
1416+
return TupleTypeElt(getType(), name, getParameterFlags());
1417+
}
1418+
1419+
/// Retrieve a copy of this tuple type element with no name
1420+
TupleTypeElt getWithoutName() const { return getWithName(Identifier()); }
13441421
};
13451422

13461423
inline Type getTupleEltType(const TupleTypeElt &elt) {
@@ -2357,11 +2434,20 @@ struct CallArgParam {
23572434
/// Whether the parameter has a default argument. Not valid for arguments.
23582435
bool HasDefaultArgument = false;
23592436

2360-
/// Whether the parameter is variadic. Not valid for arguments.
2361-
bool Variadic = false;
2437+
/// Parameter specific flags, not valid for arguments
2438+
ParameterTypeFlags parameterFlags = {};
23622439

23632440
/// Whether the argument or parameter has a label.
23642441
bool hasLabel() const { return !Label.empty(); }
2442+
2443+
/// Whether the parameter is varargs
2444+
bool isVariadic() const { return parameterFlags.isVariadic(); }
2445+
2446+
/// Whether the parameter is autoclosure
2447+
bool isAutoClosure() const { return parameterFlags.isAutoClosure(); }
2448+
2449+
/// Whether the parameter is escaping
2450+
bool isEscaping() const { return parameterFlags.isEscaping(); }
23652451
};
23662452

23672453
/// Break an argument type into an array of \c CallArgParams.
@@ -4445,16 +4531,19 @@ inline bool TypeBase::mayHaveSuperclass() {
44454531
return is<DynamicSelfType>();
44464532
}
44474533

4448-
inline TupleTypeElt::TupleTypeElt(Type ty,
4449-
Identifier name,
4450-
bool isVariadic)
4451-
: NameAndVariadic(name, isVariadic), ElementType(ty)
4452-
{
4534+
inline TupleTypeElt::TupleTypeElt(Type ty, Identifier name, bool isVariadic,
4535+
bool isAutoClosure, bool isEscaping)
4536+
: Name(name), ElementType(ty),
4537+
Flags(isVariadic, isAutoClosure, isEscaping) {
44534538
assert(!isVariadic ||
44544539
isa<ErrorType>(ty.getPointer()) ||
44554540
isa<ArraySliceType>(ty.getPointer()) ||
44564541
(isa<BoundGenericType>(ty.getPointer()) &&
44574542
ty->castTo<BoundGenericType>()->getGenericArgs().size() == 1));
4543+
assert(!isAutoClosure || (ty->is<AnyFunctionType>() &&
4544+
ty->castTo<AnyFunctionType>()->isAutoClosure()));
4545+
assert(!isEscaping || (ty->is<AnyFunctionType>() &&
4546+
!ty->castTo<AnyFunctionType>()->isNoEscape()));
44584547
}
44594548

44604549
inline Type TupleTypeElt::getVarargBaseTy(Type VarArgT) {
@@ -4469,6 +4558,16 @@ inline Type TupleTypeElt::getVarargBaseTy(Type VarArgT) {
44694558
return T;
44704559
}
44714560

4561+
/// Create one from what's present in the parameter decl and type
4562+
inline ParameterTypeFlags
4563+
ParameterTypeFlags::fromParameterType(Type paramTy, bool isVariadic) {
4564+
bool autoclosure = paramTy->is<AnyFunctionType>() &&
4565+
paramTy->castTo<AnyFunctionType>()->isAutoClosure();
4566+
bool escaping = paramTy->is<AnyFunctionType>() &&
4567+
!paramTy->castTo<AnyFunctionType>()->isNoEscape();
4568+
return {isVariadic, autoclosure, escaping};
4569+
}
4570+
44724571
inline Identifier SubstitutableType::getName() const {
44734572
if (auto Archetype = dyn_cast<ArchetypeType>(this))
44744573
return Archetype->getName();

include/swift/Serialization/ModuleFormat.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const uint16_t VERSION_MAJOR = 0;
5353
/// in source control, you should also update the comment to briefly
5454
/// describe what change you made. The content of this comment isn't important;
5555
/// it just ensures a conflict if two people change the module format.
56-
const uint16_t VERSION_MINOR = 260; // Last change: open
56+
const uint16_t VERSION_MINOR = 269; // Last change: parameter type flags
5757

5858
using DeclID = PointerEmbeddedInt<unsigned, 31>;
5959
using DeclIDField = BCFixed<31>;
@@ -570,7 +570,10 @@ namespace decls_block {
570570

571571
using ParenTypeLayout = BCRecordLayout<
572572
PAREN_TYPE,
573-
TypeIDField // inner type
573+
TypeIDField, // inner type
574+
BCFixed<1>, // vararg?
575+
BCFixed<1>, // autoclosure?
576+
BCFixed<1> // escaping?
574577
>;
575578

576579
using TupleTypeLayout = BCRecordLayout<
@@ -579,9 +582,11 @@ namespace decls_block {
579582

580583
using TupleTypeEltLayout = BCRecordLayout<
581584
TUPLE_TYPE_ELT,
582-
IdentifierIDField, // name
583-
TypeIDField, // type
584-
BCFixed<1> // vararg?
585+
IdentifierIDField, // name
586+
TypeIDField, // type
587+
BCFixed<1>, // vararg?
588+
BCFixed<1>, // autoclosure?
589+
BCFixed<1> // escaping?
585590
>;
586591

587592
using FunctionTypeLayout = BCRecordLayout<

lib/AST/ASTContext.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ struct ASTContext::Implementation {
299299
llvm::DenseMap<std::pair<Type, Type>, DictionaryType *> DictionaryTypes;
300300
llvm::DenseMap<Type, OptionalType*> OptionalTypes;
301301
llvm::DenseMap<Type, ImplicitlyUnwrappedOptionalType*> ImplicitlyUnwrappedOptionalTypes;
302-
llvm::DenseMap<Type, ParenType*> ParenTypes;
302+
llvm::DenseMap<std::pair<Type, unsigned>, ParenType*> ParenTypes;
303303
llvm::DenseMap<uintptr_t, ReferenceStorageType*> ReferenceStorageTypes;
304304
llvm::DenseMap<Type, LValueType*> LValueTypes;
305305
llvm::DenseMap<Type, InOutType*> InOutTypes;
@@ -2637,13 +2637,14 @@ BuiltinVectorType *BuiltinVectorType::get(const ASTContext &context,
26372637
return vecTy;
26382638
}
26392639

2640-
2641-
ParenType *ParenType::get(const ASTContext &C, Type underlying) {
2640+
ParenType *ParenType::get(const ASTContext &C, Type underlying,
2641+
ParameterTypeFlags flags) {
26422642
auto properties = underlying->getRecursiveProperties();
26432643
auto arena = getArena(properties);
2644-
ParenType *&Result = C.Impl.getArena(arena).ParenTypes[underlying];
2644+
ParenType *&Result =
2645+
C.Impl.getArena(arena).ParenTypes[{underlying, flags.toRaw()}];
26452646
if (Result == 0) {
2646-
Result = new (C, arena) ParenType(underlying, properties);
2647+
Result = new (C, arena) ParenType(underlying, properties, flags);
26472648
}
26482649
return Result;
26492650
}
@@ -2656,15 +2657,17 @@ void TupleType::Profile(llvm::FoldingSetNodeID &ID,
26562657
ArrayRef<TupleTypeElt> Fields) {
26572658
ID.AddInteger(Fields.size());
26582659
for (const TupleTypeElt &Elt : Fields) {
2659-
ID.AddPointer(Elt.NameAndVariadic.getOpaqueValue());
2660+
ID.AddPointer(Elt.Name.get());
26602661
ID.AddPointer(Elt.getType().getPointer());
2662+
ID.AddInteger(Elt.Flags.toRaw());
26612663
}
26622664
}
26632665

26642666
/// getTupleType - Return the uniqued tuple type with the specified elements.
26652667
Type TupleType::get(ArrayRef<TupleTypeElt> Fields, const ASTContext &C) {
26662668
if (Fields.size() == 1 && !Fields[0].isVararg() && !Fields[0].hasName())
2667-
return ParenType::get(C, Fields[0].getType());
2669+
return ParenType::get(C, Fields[0].getType(),
2670+
Fields[0].getParameterFlags());
26682671

26692672
RecursiveTypeProperties properties;
26702673
for (const TupleTypeElt &Elt : Fields) {

lib/AST/ASTDumper.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2621,6 +2621,15 @@ namespace {
26212621
return OS;
26222622
}
26232623

2624+
void dumpParameterFlags(ParameterTypeFlags paramFlags) {
2625+
if (paramFlags.isVariadic())
2626+
printFlag("vararg");
2627+
if (paramFlags.isAutoClosure())
2628+
printFlag("autoclosure");
2629+
if (paramFlags.isEscaping())
2630+
printFlag("escaping");
2631+
}
2632+
26242633
public:
26252634
PrintType(raw_ostream &os, unsigned indent) : OS(os), Indent(indent) { }
26262635

@@ -2684,6 +2693,7 @@ namespace {
26842693

26852694
void visitParenType(ParenType *T, StringRef label) {
26862695
printCommon(T, label, "paren_type");
2696+
dumpParameterFlags(T->getParameterFlags());
26872697
printRec(T->getUnderlyingType());
26882698
OS << ")";
26892699
}
@@ -2698,9 +2708,7 @@ namespace {
26982708
PrintWithColorRAII(OS, TypeFieldColor) << "tuple_type_elt";
26992709
if (elt.hasName())
27002710
printField("name", elt.getName().str());
2701-
if (elt.isVararg())
2702-
printFlag("vararg");
2703-
2711+
dumpParameterFlags(elt.getParameterFlags());
27042712
printRec(elt.getType());
27052713
OS << ")";
27062714
}
@@ -2911,10 +2919,7 @@ namespace {
29112919
}
29122920

29132921
printFlag(T->isAutoClosure(), "autoclosure");
2914-
2915-
// Dump out either @noescape or @escaping
2916-
printFlag(!T->isNoEscape(), "@escaping");
2917-
2922+
printFlag(!T->isNoEscape(), "escaping");
29182923
printFlag(T->throws(), "throws");
29192924

29202925
printRec("input", T->getInput());

0 commit comments

Comments
 (0)