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:
Doug Gregor
2013-07-18 18:49:32 +00:00
parent 457f27ccac
commit ad1a9ac2c3
13 changed files with 133 additions and 73 deletions

View File

@@ -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 {

View File

@@ -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());
}
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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()));
}

View File

@@ -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 {

View File

@@ -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());

View File

@@ -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;

View File

@@ -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));
}

View File

@@ -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;
}

View File

@@ -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});
}
}

View File

@@ -300,6 +300,7 @@ namespace decls_block {
TUPLE_TYPE_ELT,
IdentifierIDField, // name
TypeIDField, // type
DefaultArgumentField, // default argument
BCFixed<1> // vararg?
>;

View File

@@ -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());
}