Skip to content

Change the underlying type of TypeAliasDecls to an interface type #6321

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
Show file tree
Hide file tree
Changes from all commits
Commits
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
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