Skip to content

Commit c9e57af

Browse files
authored
Merge pull request #4174 from nkcsgexi/type-translate
[CodeCompletion] Refactor archetype transform to avoid using recursion.
2 parents adee860 + 2ae2368 commit c9e57af

File tree

2 files changed

+102
-61
lines changed

2 files changed

+102
-61
lines changed

include/swift/IDE/Utils.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -198,14 +198,12 @@ class SemaLocResolver : public SourceEntityWalker {
198198
} // namespace ide
199199

200200
class ArchetypeTransformer {
201-
std::function<Type(Type)> TheFunc = nullptr;
202-
DeclContext *DC;
203-
Type BaseTy;
204-
llvm::DenseMap<TypeBase *, Type> Cache;
205-
TypeSubstitutionMap Map;
201+
struct Implementation;
202+
Implementation &Impl;
206203
public:
207204
ArchetypeTransformer(DeclContext *DC, Type Ty);
208205
llvm::function_ref<Type(Type)> getTransformerFunc();
206+
~ArchetypeTransformer();
209207
};
210208
} // namespace swift
211209

lib/IDE/CodeCompletion.cpp

Lines changed: 99 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,71 +1450,114 @@ void CodeCompletionCallbacksImpl::completeExpr() {
14501450
deliverCompletionResults();
14511451
}
14521452

1453+
struct ArchetypeTransformer::Implementation {
1454+
DeclContext *DC;
1455+
Type BaseTy;
1456+
std::function<Type(Type)> TheFunc;
1457+
TypeSubstitutionMap Map;
1458+
1459+
Implementation(DeclContext *DC, Type Ty) : DC(DC),
1460+
BaseTy(Ty->getRValueType()),
1461+
TheFunc(nullptr) {
1462+
auto D = BaseTy->getNominalOrBoundGenericNominal();
1463+
if (!D)
1464+
return;
1465+
SmallVector<Type, 3> Scrach;
1466+
auto Params = D->getInnermostGenericParamTypes();
1467+
auto Args = BaseTy->getAllGenericArgs(Scrach);
1468+
assert(Params.size() == Args.size());
1469+
for (unsigned I = 0, N = Params.size(); I < N; I++) {
1470+
Map[Params[I]->getCanonicalType()->castTo<GenericTypeParamType>()] = Args[I];
1471+
}
1472+
}
1473+
1474+
Type mapGenericTypeParam(Type Ty) {
1475+
if (auto GTP = Ty->getAs<GenericTypeParamType>()) {
1476+
for (auto It : Map) {
1477+
auto Known = It.getFirst()->getAs<GenericTypeParamType>();
1478+
if (GTP->getIndex() == Known->getIndex() &&
1479+
GTP->getDepth() == Known->getDepth()) {
1480+
return It.getSecond();
1481+
}
1482+
}
1483+
}
1484+
return Type();
1485+
}
1486+
};
1487+
14531488
ArchetypeTransformer::ArchetypeTransformer(DeclContext *DC, Type Ty) :
1454-
DC(DC), BaseTy(Ty->getRValueType()){
1455-
auto D = BaseTy->getNominalOrBoundGenericNominal();
1456-
if (!D)
1457-
return;
1458-
SmallVector<Type, 3> Scrach;
1459-
auto Params = D->getInnermostGenericParamTypes();
1460-
auto Args = BaseTy->getAllGenericArgs(Scrach);
1461-
assert(Params.size() == Args.size());
1462-
for (unsigned I = 0, N = Params.size(); I < N; I++) {
1463-
Map[Params[I]->getCanonicalType()->castTo<GenericTypeParamType>()] = Args[I];
1489+
Impl(*new Implementation(DC, Ty)){}
1490+
1491+
ArchetypeTransformer::~ArchetypeTransformer() { delete &Impl; }
1492+
1493+
static Type
1494+
resolveAssociatedType(DeclContext *DC, Type BaseTy, SubstitutableType *SubTy) {
1495+
llvm::SmallVector<Identifier, 1> Names;
1496+
for (auto *AT = SubTy; AT; AT = AT->getParent()) {
1497+
if (AT->getName().str() != "Self")
1498+
Names.insert(Names.begin(), AT->getName());
1499+
}
1500+
if (auto MT = checkMemberType(*DC, BaseTy, Names)) {
1501+
if (auto NAT = dyn_cast<NameAliasType>(MT.getPointer()))
1502+
return Type(NAT->getSinglyDesugaredType());
1503+
else
1504+
return MT;
1505+
}
1506+
return Type();
1507+
}
1508+
1509+
static Type
1510+
getConformedProtocols(DeclContext *DC, ArchetypeType *ATT) {
1511+
auto Conformances = ATT->getConformsTo();
1512+
if (Conformances.size() == 1) {
1513+
return Conformances[0]->getDeclaredType();
1514+
} else if (!Conformances.empty()) {
1515+
llvm::SmallVector<Type, 3> ConformedTypes;
1516+
for (auto PD : Conformances) {
1517+
ConformedTypes.push_back(PD->getDeclaredType());
1518+
}
1519+
return ProtocolCompositionType::get(DC->getASTContext(), ConformedTypes);
14641520
}
1521+
return Type();
14651522
}
14661523

1467-
llvm::function_ref<Type(Type)> ArchetypeTransformer::getTransformerFunc() {
1468-
if (TheFunc)
1469-
return TheFunc;
1470-
TheFunc = [&](Type Ty) {
1471-
if (Ty->getKind() != TypeKind::Archetype)
1524+
llvm::function_ref<Type(Type)>
1525+
ArchetypeTransformer::getTransformerFunc() {
1526+
if (Impl.TheFunc)
1527+
return Impl.TheFunc;
1528+
Impl.TheFunc = [&](Type Ty) {
1529+
if (!Ty->is<SubstitutableType>())
14721530
return Ty;
1473-
if (Cache.count(Ty.getPointer()) > 0) {
1474-
return Cache[Ty.getPointer()];
1475-
}
1476-
Type Result = Ty;
1477-
auto *RootArc = cast<ArchetypeType>(Result.getPointer());
1478-
llvm::SmallVector<Identifier, 1> Names;
1479-
bool SelfDerived = false;
1480-
for (auto *AT = RootArc; AT; AT = AT->getParent()) {
1481-
if (!AT->getSelfProtocol())
1482-
Names.insert(Names.begin(), AT->getName());
1483-
else
1484-
SelfDerived = true;
1485-
}
1486-
if (SelfDerived) {
1487-
if (auto MT = checkMemberType(*DC, BaseTy, Names)) {
1488-
if (auto NAT = dyn_cast<NameAliasType>(MT.getPointer())) {
1489-
Result = NAT->getSinglyDesugaredType();
1490-
} else {
1491-
Result = MT;
1531+
auto OriginalTy = Ty;
1532+
Ty = Ty->getCanonicalType();
1533+
1534+
// Try to resolve generic type params.
1535+
if (Type Result = Impl.mapGenericTypeParam(Ty))
1536+
return Result;
1537+
1538+
// Try to translate associated type with the concrete base type.
1539+
if (Type Result = resolveAssociatedType(Impl.DC, Impl.BaseTy,
1540+
Ty->getAs<SubstitutableType>())) {
1541+
return Result.transform([&](Type Input) {
1542+
if (auto *ATT = Input->getAs<ArchetypeType>()) {
1543+
if (auto Conform = getConformedProtocols(Impl.DC, ATT))
1544+
return Conform;
14921545
}
1493-
}
1494-
} else {
1495-
Result = Ty.subst(DC->getParentModule(), Map, SubstFlags::IgnoreMissing);
1496-
}
1497-
1498-
auto ATT = dyn_cast<ArchetypeType>(Result.getPointer());
1499-
if (ATT && !ATT->getParent()) {
1500-
auto Conformances = ATT->getConformsTo();
1501-
if (Conformances.size() == 1) {
1502-
Result = Conformances[0]->getDeclaredType();
1503-
} else if (!Conformances.empty()) {
1504-
llvm::SmallVector<Type, 3> ConformedTypes;
1505-
for (auto PD : Conformances) {
1506-
ConformedTypes.push_back(PD->getDeclaredType());
1507-
}
1508-
Result = ProtocolCompositionType::get(DC->getASTContext(),
1509-
ConformedTypes);
1546+
return Input;
1547+
});
1548+
}
1549+
1550+
// For those archetypes that cannot be translated, use the conformances to
1551+
// provide users' some insight.
1552+
if (auto *ATT = Ty->getAs<ArchetypeType>()) {
1553+
if (Type Result = getConformedProtocols(Impl.DC, ATT)) {
1554+
return Result;
15101555
}
15111556
}
1512-
if (Result->getKind() != TypeKind::Archetype)
1513-
Result = Result.transform(getTransformerFunc());
1514-
Cache[Ty.getPointer()] = Result;
1515-
return Result;
1557+
1558+
return OriginalTy;
15161559
};
1517-
return TheFunc;
1560+
return Impl.TheFunc;
15181561
}
15191562

15201563
namespace {

0 commit comments

Comments
 (0)