Skip to content

[AST] Bring BoundNameAliastype up to parity with NameAliasType #15499

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

Closed
Closed
17 changes: 15 additions & 2 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1574,7 +1574,8 @@ class NameAliasType : public SugarType {
/// set of substitutions to apply to make the type concrete.
class BoundNameAliasType final
: public SugarType, public llvm::FoldingSetNode,
llvm::TrailingObjects<BoundNameAliasType, Type, Substitution>
llvm::TrailingObjects<BoundNameAliasType, Type, GenericSignature *,
Substitution>
{
TypeAliasDecl *typealias;

Expand All @@ -1593,6 +1594,10 @@ class BoundNameAliasType final
return Bits.BoundNameAliasType.HasParent ? 1 : 0;
}

size_t numTrailingObjects(OverloadToken<GenericSignature *>) const {
return getNumSubstitutions() > 0 ? 1 : 0;
}

size_t numTrailingObjects(OverloadToken<Substitution>) const {
return getNumSubstitutions();
}
Expand All @@ -1603,6 +1608,13 @@ class BoundNameAliasType final
return {getTrailingObjects<Substitution>(), getNumSubstitutions()};
}

/// Retrieve the generic signature used for substitutions.
GenericSignature *getGenericSignature() const {
return getNumSubstitutions() > 0
? *getTrailingObjects<GenericSignature *>()
: nullptr;
}

public:
static BoundNameAliasType *get(TypeAliasDecl *typealias, Type parent,
const SubstitutionMap &substitutions,
Expand Down Expand Up @@ -1637,7 +1649,8 @@ class BoundNameAliasType final
void Profile(llvm::FoldingSetNodeID &id) const;

static void Profile(llvm::FoldingSetNodeID &id, TypeAliasDecl *typealias,
Type parent, const SubstitutionMap &substitutions);
Type parent, const SubstitutionMap &substitutions,
Type underlying);

// Implement isa/cast/dyncast/etc.
static bool classof(const TypeBase *T) {
Expand Down
35 changes: 25 additions & 10 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2902,12 +2902,14 @@ BoundNameAliasType::BoundNameAliasType(TypeAliasDecl *typealias, Type parent,
}

// Record the substitutions.
if (auto genericSig = typealias->getGenericSignature()) {
if (auto genericSig = substitutions.getGenericSignature()) {
SmallVector<Substitution, 4> flatSubs;
genericSig->getSubstitutions(substitutions, flatSubs);
Bits.BoundNameAliasType.NumSubstitutions = flatSubs.size();
std::copy(flatSubs.begin(), flatSubs.end(),
getTrailingObjects<Substitution>());

*getTrailingObjects<GenericSignature *>() = genericSig;
} else {
Bits.BoundNameAliasType.NumSubstitutions = 0;
}
Expand All @@ -2919,14 +2921,21 @@ BoundNameAliasType *BoundNameAliasType::get(
const SubstitutionMap &substitutions,
Type underlying) {
// Compute the recursive properties.
//
auto properties = underlying->getRecursiveProperties();
if (parent)
auto storedProperties = properties;
if (parent) {
properties |= parent->getRecursiveProperties();
auto genericSig = typealias->getGenericSignature();
if (parent->hasTypeVariable())
storedProperties |= RecursiveTypeProperties::HasTypeVariable;
}
auto genericSig = substitutions.getGenericSignature();
if (genericSig) {
for (Type gp : genericSig->getGenericParams()) {
properties |= gp.subst(substitutions, SubstFlags::UseErrorType)
->getRecursiveProperties();
auto substGP = gp.subst(substitutions, SubstFlags::UseErrorType);
properties |= substGP->getRecursiveProperties();
if (substGP->hasTypeVariable())
storedProperties |= RecursiveTypeProperties::HasTypeVariable;
}
}

Expand All @@ -2936,7 +2945,8 @@ BoundNameAliasType *BoundNameAliasType::get(

// Profile the type.
llvm::FoldingSetNodeID id;
BoundNameAliasType::Profile(id, typealias, parent, substitutions);
BoundNameAliasType::Profile(id, typealias, parent, substitutions,
underlying);

// Did we already record this type?
void *insertPos;
Expand All @@ -2947,26 +2957,31 @@ BoundNameAliasType *BoundNameAliasType::get(
// Build a new type.
unsigned numSubstitutions =
genericSig ? genericSig->getSubstitutionListSize() : 0;
assert(static_cast<bool>(genericSig) == numSubstitutions > 0);
auto size =
totalSizeToAlloc<Type, Substitution>(parent ? 1 : 0, numSubstitutions);
totalSizeToAlloc<Type, GenericSignature *, Substitution>(
parent ? 1 : 0, genericSig ? 1 : 0, numSubstitutions);
auto mem = ctx.Allocate(size, alignof(BoundNameAliasType), arena);
auto result = new (mem) BoundNameAliasType(typealias, parent, substitutions,
underlying, properties);
underlying, storedProperties);
types.InsertNode(result, insertPos);
return result;
}

void BoundNameAliasType::Profile(llvm::FoldingSetNodeID &id) const {
Profile(id, getDecl(), getParent(), getSubstitutionMap());
Profile(id, getDecl(), getParent(), getSubstitutionMap(),
Type(getSinglyDesugaredType()));
}

void BoundNameAliasType::Profile(
llvm::FoldingSetNodeID &id,
TypeAliasDecl *typealias,
Type parent, const SubstitutionMap &substitutions) {
Type parent, const SubstitutionMap &substitutions,
Type underlying) {
id.AddPointer(typealias);
id.AddPointer(parent.getPointer());
substitutions.profile(id);
id.AddPointer(underlying.getPointer());
}

// Simple accessors.
Expand Down
13 changes: 11 additions & 2 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -750,8 +750,17 @@ void ASTMangler::appendType(Type type) {
assert(DWARFMangling && "sugared types are only legal for the debugger");
auto boundAliasTy = cast<BoundNameAliasType>(tybase);

// FIXME: Mangle as a generic type.
return appendType(boundAliasTy->getSinglyDesugaredType());
// It's not possible to mangle the context of the builtin module.
// FIXME: We also cannot yet mangle references to typealiases that
// involve generics.
TypeAliasDecl *decl = boundAliasTy->getDecl();
if (decl->getModuleContext() == decl->getASTContext().TheBuiltinModule) {
return appendType(boundAliasTy->getSinglyDesugaredType());
}

// For the DWARF output we want to mangle the type alias + context,
// unless the type alias references a builtin type.
return appendAnyGenericType(decl);
}

case TypeKind::Paren:
Expand Down
4 changes: 3 additions & 1 deletion lib/AST/ASTVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,8 @@ class Verifier : public ASTWalker {
abort();
}

bool foundError = type.findIf([&](Type type) -> bool {
bool foundError = type->hasArchetype() &&
type->getCanonicalType().findIf([&](Type type) -> bool {
if (auto archetype = type->getAs<ArchetypeType>()) {
// Only visit each archetype once.
if (!visitedArchetypes.insert(archetype).second)
Expand Down Expand Up @@ -2116,6 +2117,7 @@ class Verifier : public ASTWalker {
// Make sure that there are no archetypes in the interface type.
if (VD->getDeclContext()->isTypeContext() &&
!hasEnclosingFunctionContext(VD->getDeclContext()) &&
VD->getInterfaceType()->hasArchetype() &&
VD->getInterfaceType().findIf([](Type type) {
return type->is<ArchetypeType>();
})) {
Expand Down
4 changes: 2 additions & 2 deletions lib/AST/DeclContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ DeclContext::getAsTypeOrTypeExtensionContext() const {
auto type = ext->getExtendedType();
if (!type) return nullptr;

do {
while (true) {
// expected case: we reference a nominal type (potentially through sugar)
if (auto nominal = type->getAnyNominal())
return nominal;
Expand All @@ -73,7 +73,7 @@ DeclContext::getAsTypeOrTypeExtensionContext() const {
}

return nullptr;
} while (true);
}
}

/// If this DeclContext is a NominalType declaration or an
Expand Down
32 changes: 18 additions & 14 deletions lib/AST/DiagnosticEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,30 +327,34 @@ static void formatSelectionArgument(StringRef ModifierArguments,
}

static bool isInterestingTypealias(Type type) {
// Bound name alias types are always interesting.
if (isa<BoundNameAliasType>(type.getPointer())) return true;

auto aliasTy = dyn_cast<NameAliasType>(type.getPointer());
if (!aliasTy)
return false;
if (aliasTy->getDecl() == type->getASTContext().getVoidDecl())
return false;
if (type->is<BuiltinType>())
// Dig out the typealias declaration, if there is one.
TypeAliasDecl *aliasDecl = nullptr;
if (auto aliasTy = dyn_cast<NameAliasType>(type.getPointer()))
aliasDecl = aliasTy->getDecl();
else if (auto boundAliasTy = dyn_cast<BoundNameAliasType>(type.getPointer()))
aliasDecl = boundAliasTy->getDecl();
else
return false;

auto aliasDecl = aliasTy->getDecl();
if (aliasDecl == type->getASTContext().getVoidDecl())
return false;

// The 'Swift.AnyObject' typealias is not 'interesting'.
if (aliasDecl->getName() ==
aliasDecl->getASTContext().getIdentifier("AnyObject") &&
aliasDecl->getASTContext().getIdentifier("AnyObject") &&
aliasDecl->getParentModule()->isStdlibModule()) {
return false;
}

auto underlyingTy = aliasDecl->getUnderlyingTypeLoc().getType();

if (aliasDecl->isCompatibilityAlias())
// Compatibility aliases are only interesting insofar as their underlying
// types are interesting.
if (aliasDecl->isCompatibilityAlias()) {
auto underlyingTy = aliasDecl->getUnderlyingTypeLoc().getType();
return isInterestingTypealias(underlyingTy);
}

// Builtin types are never interesting typealiases.
if (type->is<BuiltinType>()) return false;

return true;
}
Expand Down
3 changes: 3 additions & 0 deletions lib/AST/PrettyStackTrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ namespace {
Decl *visitNameAliasType(NameAliasType *type) {
return type->getDecl();
}
Decl *visitBoundNameAliasType(BoundNameAliasType *type) {
return type->getDecl();
}
};
} // end anonymous namespace

Expand Down
3 changes: 3 additions & 0 deletions lib/AST/SubstitutionMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,9 @@ void SubstitutionMap::dump() const {
}

void SubstitutionMap::profile(llvm::FoldingSetNodeID &id) const {
// Generic signature.
id.AddPointer(genericSig);

if (empty() || !genericSig) return;

// Replacement types.
Expand Down
26 changes: 18 additions & 8 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1299,7 +1299,7 @@ Type SugarType::getSinglyDesugaredTypeSlow() {
}

SubstitutionMap BoundNameAliasType::getSubstitutionMap() const {
if (auto genericSig = typealias->getGenericSignature())
if (auto genericSig = getGenericSignature())
return genericSig->getSubstitutionMap(getSubstitutionList());

return SubstitutionMap();
Expand Down Expand Up @@ -2837,10 +2837,16 @@ static Type getMemberForBaseType(LookupConformanceFn lookupConformances,

// This is a hacky feature allowing code completion to migrate to
// using Type::subst() without changing output.
if (options & SubstFlags::DesugarMemberTypes)
if (auto *aliasType = dyn_cast<NameAliasType>(witness.getPointer()))
if (options & SubstFlags::DesugarMemberTypes) {
if (auto *aliasType = dyn_cast<NameAliasType>(witness.getPointer())) {
if (!aliasType->is<ErrorType>())
witness = aliasType->getSinglyDesugaredType();
} else if (auto *boundAliasType =
dyn_cast<BoundNameAliasType>(witness.getPointer())) {
if (!boundAliasType->is<ErrorType>())
witness = boundAliasType->getSinglyDesugaredType();
}
}

if (witness->is<ErrorType>())
return failed();
Expand Down Expand Up @@ -3665,22 +3671,26 @@ case TypeKind::Id:

Type oldParentType = alias->getParent();
Type newParentType;
if (oldParentType) {
if (oldParentType && !oldParentType->hasTypeParameter() &&
!oldParentType->hasArchetype()) {
newParentType = oldParentType.transformRec(fn);
if (!newParentType) return Type();
if (!newParentType) return newUnderlyingType;
}

auto subMap = alias->getSubstitutionMap();
auto genericSig = alias->getDecl()->getGenericSignature();
if (genericSig) {
if (auto genericSig = subMap.getGenericSignature()) {
for (Type gp : genericSig->getGenericParams()) {
Type oldReplacementType = gp.subst(subMap);
if (!oldReplacementType)
return newUnderlyingType;

if (oldReplacementType->hasTypeParameter() ||
oldReplacementType->hasArchetype())
return newUnderlyingType;

Type newReplacementType = oldReplacementType.transformRec(fn);
if (!newReplacementType)
return Type();
return newUnderlyingType;

// If anything changed with the replacement type, we lose the sugar.
// FIXME: This is really unfortunate.
Expand Down
8 changes: 8 additions & 0 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2500,6 +2500,14 @@ namespace {
if (auto *NAT = dyn_cast<NameAliasType>(SwiftType.getPointer()))
return NAT->getDecl();

// Don't create an extra typealias in the imported module because
// doing so will cause confusion (or even lookup ambiguity) between
// the name in the imported module and the same name in the
// standard library.
if (auto *BNAT =
dyn_cast<BoundNameAliasType>(SwiftType.getPointer()))
return BNAT->getDecl();

auto *NTD = SwiftType->getAnyNominal();
assert(NTD);
return NTD;
Expand Down
2 changes: 2 additions & 0 deletions lib/ClangImporter/ImportType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ namespace {
return Type();
if (auto *NAT = dyn_cast<NameAliasType>(T.getPointer()))
return NAT->getSinglyDesugaredType();
if (auto *BNAT = dyn_cast<BoundNameAliasType>(T.getPointer()))
return BNAT->getSinglyDesugaredType();
return T;
}

Expand Down
7 changes: 4 additions & 3 deletions lib/IDE/CodeCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2927,9 +2927,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
Optional<Type> Result = None;
if (auto AT = MT->getInstanceType()) {
if (!CD->getInterfaceType()->is<ErrorType>() &&
isa<NameAliasType>(AT.getPointer()) &&
AT->getDesugaredType() ==
CD->getResultInterfaceType().getPointer())
((isa<NameAliasType>(AT.getPointer()) ||
isa<BoundNameAliasType>(AT.getPointer())) &&
AT->getDesugaredType() ==
CD->getResultInterfaceType().getPointer()))
Result = AT;
}
addConstructorCall(CD, Reason, None, Result);
Expand Down
Loading