mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Eliminate default argument expressions from the type system.
Elements of a tuple type now know if there is a default argument, and what kind of default argument it is (callee side, __FILE__, __LINE__, __COLUMN__), but they don't have an actual expression. There are a number of cleanups this enables that will follow. Note that the serialization support is as-yet-untested. Swift SVN r6351
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#define SWIFT_TYPES_H
|
||||
|
||||
#include "swift/AST/DeclContext.h"
|
||||
#include "swift/AST/DefaultArgumentKind.h"
|
||||
#include "swift/AST/Ownership.h"
|
||||
#include "swift/AST/Type.h"
|
||||
#include "swift/AST/TypeLoc.h"
|
||||
@@ -531,43 +532,79 @@ public:
|
||||
|
||||
/// TupleTypeElt - This represents a single element of a tuple.
|
||||
class TupleTypeElt {
|
||||
/// Name - An optional name for the field.
|
||||
/// An optional name for the field.
|
||||
Identifier Name;
|
||||
|
||||
/// Describes whether this element is variadic or what kind of default
|
||||
/// argument it stores.
|
||||
enum class DefaultArgOrVarArg : uint8_t {
|
||||
/// Neither variadic nor
|
||||
None,
|
||||
/// Variadic.
|
||||
VarArg,
|
||||
/// It has a normal default argument.
|
||||
DefaultArgument,
|
||||
/// It has a caller-provided __FILE__ default argument.
|
||||
FileArgument,
|
||||
/// It has a caller-provided __LINE__ default argument.
|
||||
LineArgument,
|
||||
/// It has a caller-provided __COLUMN__ default argument.
|
||||
ColumnArgument
|
||||
};
|
||||
|
||||
/// \brief This is the type of the field, which is mandatory, along with a bit
|
||||
/// indicating whether this is a vararg.
|
||||
llvm::PointerIntPair<Type, 1, bool> TyAndVararg;
|
||||
|
||||
/// Init - This is a default value for the tuple element, used if an explicit
|
||||
/// value is not specified.
|
||||
ExprHandle *Init;
|
||||
llvm::PointerIntPair<Type, 3, DefaultArgOrVarArg> TyAndDefaultOrVarArg;
|
||||
|
||||
public:
|
||||
TupleTypeElt() = default;
|
||||
inline /*implicit*/ TupleTypeElt(Type ty,
|
||||
Identifier name = Identifier(),
|
||||
ExprHandle *init = nullptr,
|
||||
DefaultArgumentKind defaultArg =
|
||||
DefaultArgumentKind::None,
|
||||
bool isVarArg = false);
|
||||
|
||||
/*implicit*/ TupleTypeElt(TypeBase *Ty)
|
||||
: Name(Identifier()), TyAndVararg(Ty, false), Init(nullptr) { }
|
||||
: Name(Identifier()), TyAndDefaultOrVarArg(Ty, DefaultArgOrVarArg::None) { }
|
||||
|
||||
bool hasName() const { return !Name.empty(); }
|
||||
Identifier getName() const { return Name; }
|
||||
|
||||
Type getType() const { return TyAndVararg.getPointer(); }
|
||||
bool isVararg() const { return TyAndVararg.getInt(); }
|
||||
inline Type getVarargBaseTy() const;
|
||||
Type getType() const { return TyAndDefaultOrVarArg.getPointer(); }
|
||||
|
||||
/// \brief Retrieve a copy of this tuple type element with the type replaced.
|
||||
TupleTypeElt getWithType(Type T) const {
|
||||
TupleTypeElt Result(*this);
|
||||
Result.TyAndVararg.setPointerAndInt(T, false);
|
||||
return Result;
|
||||
/// Determine whether this field is variadic.
|
||||
bool isVararg() const {
|
||||
return TyAndDefaultOrVarArg.getInt() == DefaultArgOrVarArg::VarArg;
|
||||
}
|
||||
|
||||
bool hasInit() const { return Init != nullptr; }
|
||||
ExprHandle *getInit() const { return Init; }
|
||||
void setInit(ExprHandle *E) { Init = E; }
|
||||
/// Retrieve the kind of default argument available on this field.
|
||||
DefaultArgumentKind getDefaultArgKind() const {
|
||||
switch (TyAndDefaultOrVarArg.getInt()) {
|
||||
case DefaultArgOrVarArg::None:
|
||||
case DefaultArgOrVarArg::VarArg:
|
||||
return DefaultArgumentKind::None;
|
||||
case DefaultArgOrVarArg::DefaultArgument:
|
||||
return DefaultArgumentKind::Normal;
|
||||
case DefaultArgOrVarArg::FileArgument:
|
||||
return DefaultArgumentKind::File;
|
||||
case DefaultArgOrVarArg::LineArgument:
|
||||
return DefaultArgumentKind::Line;
|
||||
case DefaultArgOrVarArg::ColumnArgument:
|
||||
return DefaultArgumentKind::Column;
|
||||
}
|
||||
}
|
||||
|
||||
inline Type getVarargBaseTy() const;
|
||||
|
||||
/// Retrieve a copy of this tuple type element with the type replaced.
|
||||
TupleTypeElt getWithType(Type T) const {
|
||||
return TupleTypeElt(T, getName(), getDefaultArgKind());
|
||||
}
|
||||
|
||||
/// Determine whether this tuple element has an initializer.
|
||||
bool hasInit() const {
|
||||
return getDefaultArgKind() != DefaultArgumentKind::None;
|
||||
}
|
||||
};
|
||||
|
||||
/// TupleType - A tuple is a parenthesized list of types where each name has an
|
||||
@@ -607,12 +644,6 @@ public:
|
||||
/// return -1.
|
||||
int getFieldForScalarInit() const;
|
||||
|
||||
|
||||
/// updateInitializedElementType - This methods updates the element type and
|
||||
/// initializer for a non-canonical TupleType that has an initializer for the
|
||||
/// specified element. This should only be used by TypeChecker.
|
||||
void updateInitializedElementType(unsigned EltNo, Type NewTy);
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
@@ -1858,12 +1889,39 @@ inline bool TypeBase::mayHaveSuperclass() {
|
||||
|
||||
inline TupleTypeElt::TupleTypeElt(Type ty,
|
||||
Identifier name,
|
||||
ExprHandle *init,
|
||||
DefaultArgumentKind defArg,
|
||||
bool isVarArg)
|
||||
: Name(name), TyAndVararg(ty, isVarArg), Init(init) {
|
||||
: Name(name), TyAndDefaultOrVarArg(ty.getPointer(),
|
||||
DefaultArgOrVarArg::None) {
|
||||
assert(!isVarArg || isa<ArraySliceType>(ty.getPointer()) ||
|
||||
(isa<BoundGenericType>(ty.getPointer()) &&
|
||||
ty->castTo<BoundGenericType>()->getGenericArgs().size() == 1));
|
||||
|
||||
if (isVarArg) {
|
||||
assert(defArg == DefaultArgumentKind::None && "Defaulted vararg");
|
||||
TyAndDefaultOrVarArg.setInt(DefaultArgOrVarArg::VarArg);
|
||||
} else {
|
||||
switch (defArg) {
|
||||
case DefaultArgumentKind::None:
|
||||
break;
|
||||
|
||||
case DefaultArgumentKind::Normal:
|
||||
TyAndDefaultOrVarArg.setInt(DefaultArgOrVarArg::DefaultArgument);
|
||||
break;
|
||||
|
||||
case DefaultArgumentKind::File:
|
||||
TyAndDefaultOrVarArg.setInt(DefaultArgOrVarArg::FileArgument);
|
||||
break;
|
||||
|
||||
case DefaultArgumentKind::Line:
|
||||
TyAndDefaultOrVarArg.setInt(DefaultArgOrVarArg::LineArgument);
|
||||
break;
|
||||
|
||||
case DefaultArgumentKind::Column:
|
||||
TyAndDefaultOrVarArg.setInt(DefaultArgOrVarArg::ColumnArgument);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline Type TupleTypeElt::getVarargBaseTy() const {
|
||||
|
||||
@@ -374,7 +374,7 @@ void TupleType::Profile(llvm::FoldingSetNodeID &ID,
|
||||
for (const TupleTypeElt &Elt : Fields) {
|
||||
ID.AddPointer(Elt.getType().getPointer());
|
||||
ID.AddPointer(Elt.getName().get());
|
||||
ID.AddPointer(Elt.getInit());
|
||||
ID.AddInteger((unsigned)Elt.getDefaultArgKind());
|
||||
ID.AddBoolean(Elt.isVararg());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -522,14 +522,16 @@ static Type getStrippedType(const ASTContext &context, Type type,
|
||||
Type EltTy = getStrippedType(context, Elt.getType(),
|
||||
stripLabels, stripDefaultArgs);
|
||||
if (Rebuild || EltTy.getPointer() != Elt.getType().getPointer() ||
|
||||
(Elt.getInit() && stripDefaultArgs) ||
|
||||
(Elt.hasInit() && stripDefaultArgs) ||
|
||||
(!Elt.getName().empty() && stripLabels)) {
|
||||
if (!Rebuild) {
|
||||
Elements.reserve(TupleTy->getFields().size());
|
||||
for (unsigned I = 0; I != Idx; ++I) {
|
||||
const TupleTypeElt &Elt = TupleTy->getFields()[I];
|
||||
Identifier newName = stripLabels? Identifier() : Elt.getName();
|
||||
ExprHandle *newDefArg = stripDefaultArgs? nullptr : Elt.getInit();
|
||||
DefaultArgumentKind newDefArg
|
||||
= stripDefaultArgs? DefaultArgumentKind::None
|
||||
: Elt.getDefaultArgKind();
|
||||
Elements.push_back(TupleTypeElt(Elt.getType(), newName, newDefArg,
|
||||
Elt.isVararg()));
|
||||
}
|
||||
@@ -537,7 +539,9 @@ static Type getStrippedType(const ASTContext &context, Type type,
|
||||
}
|
||||
|
||||
Identifier newName = stripLabels? Identifier() : Elt.getName();
|
||||
ExprHandle *newDefArg = stripDefaultArgs? nullptr : Elt.getInit();
|
||||
DefaultArgumentKind newDefArg
|
||||
= stripDefaultArgs? DefaultArgumentKind::None
|
||||
: Elt.getDefaultArgKind();
|
||||
Elements.push_back(TupleTypeElt(EltTy, newName, newDefArg,
|
||||
Elt.isVararg()));
|
||||
}
|
||||
@@ -794,7 +798,7 @@ CanType TypeBase::getCanonicalType() {
|
||||
"Cannot get canonical type of un-typechecked TupleType!");
|
||||
CanElts.push_back(TupleTypeElt(field.getType()->getCanonicalType(),
|
||||
field.getName(),
|
||||
field.getInit(),
|
||||
field.getDefaultArgKind(),
|
||||
field.isVararg()));
|
||||
}
|
||||
|
||||
@@ -1145,15 +1149,6 @@ int TupleType::getFieldForScalarInit() const {
|
||||
}
|
||||
|
||||
|
||||
/// updateInitializedElementType - This methods updates the element type and
|
||||
/// initializer for a non-canonical TupleType that has an initializer for the
|
||||
/// specified element. This should only be used by TypeChecker.
|
||||
void TupleType::updateInitializedElementType(unsigned EltNo, Type NewTy) {
|
||||
TupleTypeElt &Elt = const_cast<TupleTypeElt&>(Fields[EltNo]);
|
||||
assert(Elt.hasInit() && "Can only update elements with default values");
|
||||
Elt = TupleTypeElt(NewTy, Elt.getName(), Elt.getInit());
|
||||
}
|
||||
|
||||
bool SubstitutableType::requiresClass() const {
|
||||
if (Superclass)
|
||||
return true;
|
||||
|
||||
@@ -88,7 +88,7 @@ static Type getBridgedInputType(TypeConverter &tc,
|
||||
changed = true;
|
||||
bridgedFields.push_back(TupleTypeElt(bridged,
|
||||
field.getName(),
|
||||
field.getInit(),
|
||||
field.getDefaultArgKind(),
|
||||
field.isVararg()));
|
||||
} else {
|
||||
bridgedFields.push_back(field);
|
||||
|
||||
@@ -2423,7 +2423,7 @@ static Type stripInitializers(TypeChecker &tc, Type origType) {
|
||||
for (const auto &field : tupleTy->getFields()) {
|
||||
fields.push_back(TupleTypeElt(field.getType(),
|
||||
field.getName(),
|
||||
nullptr,
|
||||
DefaultArgumentKind::None,
|
||||
field.isVararg()));
|
||||
|
||||
}
|
||||
|
||||
@@ -1849,7 +1849,7 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr, TupleType *fromTuple,
|
||||
|
||||
toSugarFields.push_back(TupleTypeElt(fromEltType,
|
||||
toElt.getName(),
|
||||
toElt.getInit(),
|
||||
toElt.getDefaultArgKind(),
|
||||
toElt.isVararg()));
|
||||
fromTupleExprFields[sources[i]] = fromElt;
|
||||
hasInits |= toElt.hasInit();
|
||||
@@ -1878,11 +1878,11 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr, TupleType *fromTuple,
|
||||
// Record the sugared field name.
|
||||
toSugarFields.push_back(TupleTypeElt(convertedElt->getType(),
|
||||
toElt.getName(),
|
||||
toElt.getInit(),
|
||||
toElt.getDefaultArgKind(),
|
||||
toElt.isVararg()));
|
||||
fromTupleExprFields[sources[i]] = TupleTypeElt(convertedElt->getType(),
|
||||
fromElt.getName(),
|
||||
fromElt.getInit(),
|
||||
fromElt.getDefaultArgKind(),
|
||||
fromElt.isVararg());
|
||||
hasInits |= toElt.hasInit();
|
||||
}
|
||||
@@ -1926,7 +1926,7 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr, TupleType *fromTuple,
|
||||
fromTupleExprFields[fromFieldIdx] = TupleTypeElt(
|
||||
convertedElt->getType(),
|
||||
fromElt.getName(),
|
||||
fromElt.getInit(),
|
||||
fromElt.getDefaultArgKind(),
|
||||
fromElt.isVararg());
|
||||
}
|
||||
|
||||
@@ -2038,7 +2038,7 @@ Expr *ExprRewriter::coerceScalarToTuple(Expr *expr, TupleType *toTuple,
|
||||
|
||||
sugarFields.push_back(TupleTypeElt(field.getType(),
|
||||
field.getName(),
|
||||
field.getInit(),
|
||||
field.getDefaultArgKind(),
|
||||
true));
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -472,8 +472,8 @@ namespace {
|
||||
Type arrayEltsTy = tc.getArraySliceType(expr->getLoc(), arrayElementTy);
|
||||
TupleTypeElt arrayEltsElt{arrayEltsTy,
|
||||
/*name=*/ Identifier(),
|
||||
/*init=*/ nullptr,
|
||||
arrayElementTy};
|
||||
DefaultArgumentKind::None,
|
||||
/*isVararg=*/true};
|
||||
Type arrayEltsTupleTy = TupleType::get(arrayEltsElt, C);
|
||||
CS.addConstraint(ConstraintKind::Conversion,
|
||||
expr->getSubExpr()->getType(),
|
||||
@@ -531,8 +531,8 @@ namespace {
|
||||
Type dictionaryEltsTy = tc.getArraySliceType(expr->getLoc(), elementTy);
|
||||
TupleTypeElt dictionaryEltsElt(dictionaryEltsTy,
|
||||
/*name=*/ Identifier(),
|
||||
/*init=*/ nullptr,
|
||||
/*isVarArg=*/ true);
|
||||
DefaultArgumentKind::None,
|
||||
/*isVararg=*/true);
|
||||
Type dictionaryEltsTupleTy = TupleType::get(dictionaryEltsElt, C);
|
||||
CS.addConstraint(ConstraintKind::Conversion,
|
||||
expr->getSubExpr()->getType(),
|
||||
@@ -606,7 +606,8 @@ namespace {
|
||||
LocatorPathElt::getTupleElement(i)));
|
||||
auto name = findPatternName(tupleElt.getPattern());
|
||||
Type varArgBaseTy;
|
||||
tupleTypeElts.push_back(TupleTypeElt(eltTy, name, tupleElt.getInit(),
|
||||
tupleTypeElts.push_back(TupleTypeElt(eltTy, name,
|
||||
tupleElt.getDefaultArgKind(),
|
||||
isVararg));
|
||||
}
|
||||
return TupleType::get(tupleTypeElts, CS.getASTContext());
|
||||
|
||||
@@ -1112,11 +1112,7 @@ bool TypeChecker::isDefaultInitializable(Type ty, Expr **initializer) {
|
||||
llvm::SmallVector<Expr *, 4> eltInits;
|
||||
llvm::SmallVector<Identifier, 4> eltNames;
|
||||
for (auto &elt : ty->castTo<TupleType>()->getFields()) {
|
||||
// If the element has an initializer, we're all set.
|
||||
if (elt.getInit()) {
|
||||
// FIXME: Add a DefaultTupleArgumentExpr node here?
|
||||
continue;
|
||||
}
|
||||
assert(!elt.hasInit() && "Initializers can't appear here");
|
||||
|
||||
// Check whether the element is default-initializable.
|
||||
Expr *eltInit = nullptr;
|
||||
@@ -1195,7 +1191,7 @@ bool TypeChecker::isDefaultInitializable(Type ty, Expr **initializer) {
|
||||
// Check whether any of the tuple elements are missing an initializer.
|
||||
bool missingInit = false;
|
||||
for (auto &elt : paramTuple->getFields()) {
|
||||
if (elt.getInit())
|
||||
if (elt.hasInit())
|
||||
continue;
|
||||
|
||||
missingInit = true;
|
||||
|
||||
@@ -529,7 +529,8 @@ bool TypeChecker::typeCheckPattern(Pattern *P, DeclContext *dc,
|
||||
init->setExpr(e, true);
|
||||
}
|
||||
|
||||
typeElts.push_back(TupleTypeElt(type, pattern->getBoundName(), init,
|
||||
typeElts.push_back(TupleTypeElt(type, pattern->getBoundName(),
|
||||
elt.getDefaultArgKind(),
|
||||
isVararg));
|
||||
}
|
||||
|
||||
|
||||
@@ -667,7 +667,7 @@ Type TypeChecker::resolveType(TypeRepr *TyR, bool allowUnboundGenerics) {
|
||||
Type ty = resolveType(namedTyR->getTypeRepr());
|
||||
if (ty->is<ErrorType>())
|
||||
return ty;
|
||||
Elements.push_back(TupleTypeElt(ty, namedTyR->getName(), nullptr));
|
||||
Elements.push_back(TupleTypeElt(ty, namedTyR->getName()));
|
||||
} else {
|
||||
Type ty = resolveType(tyR);
|
||||
if (ty->is<ErrorType>())
|
||||
@@ -680,8 +680,10 @@ Type TypeChecker::resolveType(TypeRepr *TyR, bool allowUnboundGenerics) {
|
||||
Type BaseTy = Elements.back().getType();
|
||||
Type FullTy = ArraySliceType::get(BaseTy, Context);
|
||||
Identifier Name = Elements.back().getName();
|
||||
ExprHandle *Init = Elements.back().getInit();
|
||||
Elements.back() = TupleTypeElt(FullTy, Name, Init, true);
|
||||
// FIXME: Where are we rejecting default arguments for variadic
|
||||
// parameters?
|
||||
Elements.back() = TupleTypeElt(FullTy, Name, DefaultArgumentKind::None,
|
||||
true);
|
||||
}
|
||||
|
||||
return TupleType::get(Elements, Context);
|
||||
@@ -1012,7 +1014,7 @@ Type TypeChecker::transformType(Type type,
|
||||
for (unsigned I = 0; I != Index; ++I) {
|
||||
const TupleTypeElt &FromElt =Tuple->getFields()[I];
|
||||
Elements.push_back(TupleTypeElt(FromElt.getType(), FromElt.getName(),
|
||||
FromElt.getInit(),
|
||||
FromElt.getDefaultArgKind(),
|
||||
FromElt.isVararg()));
|
||||
}
|
||||
|
||||
@@ -1020,8 +1022,8 @@ Type TypeChecker::transformType(Type type,
|
||||
}
|
||||
|
||||
// Add the new tuple element, with the new type, no initializer,
|
||||
Elements.push_back(TupleTypeElt(EltTy, Elt.getName(), Elt.getInit(),
|
||||
Elt.isVararg()));
|
||||
Elements.push_back(TupleTypeElt(EltTy, Elt.getName(),
|
||||
Elt.getDefaultArgKind(), Elt.isVararg()));
|
||||
++Index;
|
||||
}
|
||||
|
||||
|
||||
@@ -1480,14 +1480,18 @@ Type ModuleFile::getType(TypeID TID) {
|
||||
|
||||
IdentifierID nameID;
|
||||
TypeID typeID;
|
||||
uint8_t rawDefArg;
|
||||
bool isVararg;
|
||||
decls_block::TupleTypeEltLayout::readRecord(scratch, nameID, typeID,
|
||||
isVararg);
|
||||
rawDefArg, isVararg);
|
||||
|
||||
{
|
||||
BCOffsetRAII restoreOffset(DeclTypeCursor);
|
||||
elements.push_back({getType(typeID), getIdentifier(nameID),
|
||||
/*initializer=*/nullptr, isVararg});
|
||||
DefaultArgumentKind defArg = DefaultArgumentKind::None;
|
||||
if (auto actualDefArg = getActualDefaultArgKind(rawDefArg))
|
||||
defArg = *actualDefArg;
|
||||
elements.push_back({getType(typeID), getIdentifier(nameID), defArg,
|
||||
isVararg});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -300,6 +300,7 @@ namespace decls_block {
|
||||
TUPLE_TYPE_ELT,
|
||||
IdentifierIDField, // name
|
||||
TypeIDField, // type
|
||||
DefaultArgumentField, // default argument
|
||||
BCFixed<1> // vararg?
|
||||
>;
|
||||
|
||||
|
||||
@@ -1297,10 +1297,12 @@ bool Serializer::writeType(Type ty) {
|
||||
|
||||
abbrCode = DeclTypeAbbrCodes[TupleTypeEltLayout::Code];
|
||||
for (auto &elt : tupleTy->getFields()) {
|
||||
// FIXME: Handle initializers.
|
||||
uint8_t rawDefaultArg
|
||||
= getRawStableDefaultArgumentKind(elt.getDefaultArgKind());
|
||||
TupleTypeEltLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
||||
addIdentifierRef(elt.getName()),
|
||||
addTypeRef(elt.getType()),
|
||||
rawDefaultArg,
|
||||
elt.isVararg());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user