Skip to content

Commit

Permalink
Merge pull request swiftlang#6321 from slavapestov/typealias-underlyi…
Browse files Browse the repository at this point in the history
…ng-interface-type

Change the underlying type of TypeAliasDecls to an interface type
  • Loading branch information
slavapestov authored Dec 16, 2016
2 parents 4c06e45 + 2c6b9f7 commit 2ff9061
Show file tree
Hide file tree
Showing 58 changed files with 598 additions and 473 deletions.
75 changes: 25 additions & 50 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ namespace swift {
class TypeAliasDecl;
class Stmt;
class SubscriptDecl;
class UnboundGenericType;
class ValueDecl;
class VarDecl;

Expand Down Expand Up @@ -413,9 +414,10 @@ class alignas(1 << DeclAlignInBits) Decl {
friend class TypeAliasDecl;
unsigned : NumGenericTypeDeclBits;

/// Whether the underlying type is an interface type that will be lazily
/// resolved to a context type.
unsigned HasInterfaceUnderlyingType : 1;
/// Whether we have completed validation of the typealias.
/// This is necessary because unlike other declarations, a
/// typealias will not get an interface type right away.
unsigned HasCompletedValidation : 1;
};
enum { NumTypeAliasDeclBits = NumGenericTypeDeclBits + 1 };
static_assert(NumTypeAliasDeclBits <= 32, "fits in an unsigned");
Expand Down Expand Up @@ -2391,60 +2393,38 @@ class GenericTypeDecl : public TypeDecl, public DeclContext {
/// TypeAliasDecl's always have 'MetatypeType' type.
///
class TypeAliasDecl : public GenericTypeDecl {
/// The type that represents this (sugared) name alias.
mutable NameAliasType *AliasTy;

SourceLoc TypeAliasLoc; // The location of the 'typealias' keyword
mutable TypeLoc UnderlyingTy;

Type computeUnderlyingContextType() const;
TypeLoc UnderlyingTy;

public:
TypeAliasDecl(SourceLoc TypeAliasLoc, Identifier Name,
SourceLoc NameLoc, TypeLoc UnderlyingTy,
GenericParamList *GenericParams, DeclContext *DC);
SourceLoc NameLoc, GenericParamList *GenericParams,
DeclContext *DC);

SourceLoc getStartLoc() const { return TypeAliasLoc; }
SourceRange getSourceRange() const;

/// getUnderlyingType - Returns the underlying type, which is
/// assumed to have been set.
Type getUnderlyingType() const {
if (TypeAliasDeclBits.HasInterfaceUnderlyingType)
return computeUnderlyingContextType();

assert(!UnderlyingTy.getType().isNull() &&
"getting invalid underlying type");
return UnderlyingTy.getType();
}

/// computeType - Compute the type (and declared type) of this type alias;
/// can only be called after the alias type has been resolved.
void computeType();

/// \brief Determine whether this type alias has an underlying type.
bool hasUnderlyingType() const {
return !UnderlyingTy.getType().isNull();
}

TypeLoc &getUnderlyingTypeLoc() {
if (TypeAliasDeclBits.HasInterfaceUnderlyingType)
(void)computeUnderlyingContextType();

return UnderlyingTy;
}
const TypeLoc &getUnderlyingTypeLoc() const {
if (TypeAliasDeclBits.HasInterfaceUnderlyingType)
(void)computeUnderlyingContextType();

return UnderlyingTy;
}

/// Set the underlying type after deserialization.
void setDeserializedUnderlyingType(Type type);
/// Set the underlying type, for deserialization and synthesized
/// aliases.
void setUnderlyingType(Type type);

bool hasCompletedValidation() const {
return TypeAliasDeclBits.HasCompletedValidation;
}

void setHasCompletedValidation() {
TypeAliasDeclBits.HasCompletedValidation = 1;
}

/// getAliasType - Return the sugared version of this decl as a Type.
NameAliasType *getAliasType() const { return AliasTy; }
/// For generic typealiases, return the unbound generic type.
UnboundGenericType *getUnboundGenericType() const;

static bool classof(const Decl *D) {
return D->getKind() == DeclKind::TypeAlias;
Expand Down Expand Up @@ -4164,10 +4144,7 @@ class VarDecl : public AbstractStorageDecl {
/// This is the type specified, including location information.
TypeLoc typeLoc;

mutable Type typeInContext;

/// Compute the type in context from the interface type.
Type computeTypeInContextSlow() const;
Type typeInContext;

public:
VarDecl(bool IsStatic, bool IsLet, SourceLoc NameLoc, Identifier Name,
Expand All @@ -4190,15 +4167,13 @@ class VarDecl : public AbstractStorageDecl {
bool hasType() const {
// We have a type if either the type has been computed already or if
// this is a deserialized declaration with an interface type.
return typeInContext ||
(hasInterfaceType() && !getDeclContext()->getParentSourceFile());
return !typeInContext.isNull();
}

/// Get the type of the variable within its context. If the context is generic,
/// this will use archetypes.
Type getType() const {
if (!typeInContext)
return computeTypeInContextSlow();
assert(!typeInContext.isNull() && "no contextual type set yet");
return typeInContext;
}

Expand Down Expand Up @@ -4414,7 +4389,7 @@ class ParamDecl : public VarDecl {
/// type wrapping it.
Type getVarargBaseTy() const {
assert(isVariadic());
return getVarargBaseTy(getType());
return getVarargBaseTy(getInterfaceType());
}

SourceRange getSourceRange() const;
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3661,7 +3661,7 @@ static NominalTypeDecl *findUnderlyingTypeInModule(ASTContext &ctx,
if (auto typealias = dyn_cast<TypeAliasDecl>(result)) {
if (auto resolver = ctx.getLazyResolver())
resolver->resolveDeclSignature(typealias);
return typealias->getUnderlyingType()->getAnyNominal();
return typealias->getDeclaredInterfaceType()->getAnyNominal();
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,8 +460,8 @@ namespace {
void visitTypeAliasDecl(TypeAliasDecl *TAD) {
printCommon(TAD, "typealias");
OS << " type='";
if (TAD->hasUnderlyingType())
OS << TAD->getUnderlyingType().getString();
if (TAD->getUnderlyingTypeLoc().getType())
OS << TAD->getUnderlyingTypeLoc().getType().getString();
else
OS << "<<<unresolved>>>";
printInherited(TAD->getInherited());
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ void ASTMangler::appendType(Type type) {
TypeAliasDecl *decl = NameAliasTy->getDecl();
if (decl->getModuleContext() == decl->getASTContext().TheBuiltinModule) {
// It's not possible to mangle the context of the builtin module.
return appendType(decl->getUnderlyingType());
return appendType(decl->getDeclaredInterfaceType());
}

// For the DWARF output we want to mangle the type alias + context,
Expand Down
17 changes: 6 additions & 11 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2141,9 +2141,8 @@ void PrintAST::visitTypeAliasDecl(TypeAliasDecl *decl) {
printGenericSignature(genericSig, PrintParams | InnermostOnly);
});
bool ShouldPrint = true;
Type Ty;
if (decl->hasUnderlyingType())
Ty = decl->getUnderlyingType();
Type Ty = decl->getUnderlyingTypeLoc().getType();

// If the underlying type is private, don't print it.
if (Options.SkipPrivateStdlibDecls && Ty && Ty.isPrivateStdlibType())
ShouldPrint = false;
Expand Down Expand Up @@ -2338,11 +2337,11 @@ void PrintAST::visitVarDecl(VarDecl *decl) {
[&]{
Printer.printName(decl->getName());
});
if (decl->hasType()) {
if (decl->hasInterfaceType()) {
Printer << ": ";
auto tyLoc = decl->getTypeLoc();
if (!tyLoc.getTypeRepr())
tyLoc = TypeLoc::withoutLoc(decl->getType());
tyLoc = TypeLoc::withoutLoc(decl->getInterfaceType());
printTypeLoc(tyLoc);
}

Expand Down Expand Up @@ -2395,12 +2394,8 @@ void PrintAST::printOneParameter(const ParamDecl *param,

printArgName();

if (!TheTypeLoc.getTypeRepr() && param->hasType()) {
// FIXME: ParamDecls should have interface types instead
auto *DC = Current->getInnermostDeclContext();
auto type = ArchetypeBuilder::mapTypeOutOfContext(DC, param->getType());
TheTypeLoc = TypeLoc::withoutLoc(type);
}
if (!TheTypeLoc.getTypeRepr() && param->hasInterfaceType())
TheTypeLoc = TypeLoc::withoutLoc(param->getInterfaceType());

// If the parameter is variadic, we will print the "..." after it, but we have
// to strip off the added array type.
Expand Down
8 changes: 4 additions & 4 deletions lib/AST/ASTVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1704,15 +1704,15 @@ struct ASTNodeBase {};

// Variables must have materializable type, unless they are parameters,
// in which case they must either have l-value type or be anonymous.
if (!var->getType()->isMaterializable()) {
if (!var->getInterfaceType()->isMaterializable()) {
if (!isa<ParamDecl>(var)) {
Out << "Non-parameter VarDecl has non-materializable type: ";
var->getType().print(Out);
Out << "\n";
abort();
}

if (!var->getType()->is<InOutType>() && var->hasName()) {
if (!var->getInterfaceType()->is<InOutType>() && var->hasName()) {
Out << "ParamDecl may only have non-materializable tuple type "
"when it is anonymous: ";
var->getType().print(Out);
Expand All @@ -1724,15 +1724,15 @@ struct ASTNodeBase {};
// The fact that this is *directly* be a reference storage type
// cuts the code down quite a bit in getTypeOfReference.
if (var->getAttrs().hasAttribute<OwnershipAttr>() !=
isa<ReferenceStorageType>(var->getType().getPointer())) {
isa<ReferenceStorageType>(var->getInterfaceType().getPointer())) {
if (var->getAttrs().hasAttribute<OwnershipAttr>()) {
Out << "VarDecl has an ownership attribute, but its type"
" is not a ReferenceStorageType: ";
} else {
Out << "VarDecl has no ownership attribute, but its type"
" is a ReferenceStorageType: ";
}
var->getType().print(Out);
var->getInterfaceType().print(Out);
abort();
}

Expand Down
11 changes: 3 additions & 8 deletions lib/AST/ArchetypeBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,19 +413,14 @@ auto ArchetypeBuilder::PotentialArchetype::getNestedType(
// Resolve this nested type to this type alias.
pa = new PotentialArchetype(this, alias);

if (!alias->hasUnderlyingType())
if (!alias->hasInterfaceType())
builder.getLazyResolver()->resolveDeclSignature(alias);
if (!alias->hasUnderlyingType())
if (!alias->hasInterfaceType())
continue;

auto type = alias->getUnderlyingType();
auto type = alias->getDeclaredInterfaceType();
SmallVector<Identifier, 4> identifiers;

// Map the type out of its context.
if (auto genericEnv = alias->getGenericEnvironmentOfContext()) {
type = genericEnv->mapTypeOutOfContext(type);
}

if (auto existingPA = builder.resolveArchetype(type)) {
builder.addSameTypeRequirementBetweenArchetypes(pa, existingPA,
redundantSource);
Expand Down
6 changes: 5 additions & 1 deletion lib/AST/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ getBuiltinFunction(Identifier Id, ArrayRef<Type> argTypes, Type ResType,
Identifier(), SourceLoc(),
Identifier(), argType,
DC);
PD->setInterfaceType(argType);
PD->setImplicit();
params.push_back(PD);
}
Expand Down Expand Up @@ -204,10 +205,13 @@ getBuiltinGenericFunction(Identifier Id,
DeclContext *DC = &M->getMainFile(FileUnitKind::Builtin);

SmallVector<ParamDecl*, 4> params;
for (auto paramType : ArgBodyTypes) {
for (unsigned i = 0, e = ArgParamTypes.size(); i < e; i++) {
auto paramType = ArgBodyTypes[i];
auto paramIfaceType = ArgParamTypes[i].getType();
auto PD = new (Context) ParamDecl(/*IsLet*/true, SourceLoc(), SourceLoc(),
Identifier(), SourceLoc(),
Identifier(), paramType, DC);
PD->setInterfaceType(paramIfaceType);
PD->setImplicit();
params.push_back(PD);
}
Expand Down
Loading

0 comments on commit 2ff9061

Please sign in to comment.