Skip to content

Commit c373b1c

Browse files
committed
Reflection: Some improvements to substitutions
The most important change is a fix for dependent member lookup in bound generic TypeRefs. The TypeRef logic here is a similified version of what Sema does, and roughly works as follows: When looking up a member type O.M for an original type O and member type M, we first substitute O, to yield a concrete type S. Then, we look up M in the serialized conformance info section to yield the unsubstituted member type T', and apply substitutions to produce the substituted member type T. Trouble is, we were applying the wrong substitutions the second time around. If S is a bound generic type, the "base type substitutions" of S are the substitutions required to turn the fully-abstracted bound generic type into S. This might not be the same substitution map that took us from O to S. Apart from that, add some assertions that the result of a substitution is always concrete and that the substitution map must not contain all generic parameters referenced in the original type.
1 parent 22bf2dc commit c373b1c

File tree

1 file changed

+19
-41
lines changed

1 file changed

+19
-41
lines changed

include/swift/Reflection/TypeRef.h

Lines changed: 19 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -566,35 +566,25 @@ class TypeRefSubstitution
566566
TypeRefPointer visitBoundGenericTypeRef(const BoundGenericTypeRef *BG) {
567567
TypeRefVector GenericParams;
568568
for (auto Param : BG->getGenericParams())
569-
if (auto Substituted = visit(Param.get()))
570-
GenericParams.push_back(Substituted);
571-
else return nullptr;
569+
GenericParams.push_back(visit(Param.get()));
572570
return std::make_shared<BoundGenericTypeRef>(BG->getMangledName(),
573571
GenericParams);
574572
}
575573

576574
TypeRefPointer visitTupleTypeRef(const TupleTypeRef *T) {
577575
TypeRefVector Elements;
578576
for (auto Element : T->getElements()) {
579-
if (auto SubstitutedElement = visit(Element.get()))
580-
Elements.push_back(SubstitutedElement);
581-
else
582-
return nullptr;
577+
Elements.push_back(visit(Element.get()));
583578
}
584579
return std::make_shared<TupleTypeRef>(Elements, T->isVariadic());
585580
}
586581

587582
TypeRefPointer visitFunctionTypeRef(const FunctionTypeRef *F) {
588583
TypeRefVector SubstitutedArguments;
589584
for (auto Argument : F->getArguments())
590-
if (auto SubstitutedArgument = visit(Argument.get()))
591-
SubstitutedArguments.push_back(SubstitutedArgument);
592-
else
593-
return nullptr;
585+
SubstitutedArguments.push_back(visit(Argument.get()));
594586

595587
auto SubstitutedResult = visit(F->getResult().get());
596-
if (!SubstitutedResult)
597-
return nullptr;
598588

599589
return std::make_shared<FunctionTypeRef>(SubstitutedArguments,
600590
SubstitutedResult);
@@ -610,30 +600,26 @@ class TypeRefSubstitution
610600
}
611601

612602
TypeRefPointer visitMetatypeTypeRef(const MetatypeTypeRef *M) {
613-
if (auto SubstitutedInstance = visit(M->getInstanceType().get()))
614-
return MetatypeTypeRef::create(SubstitutedInstance);
615-
else
616-
return nullptr;
603+
return MetatypeTypeRef::create(visit(M->getInstanceType().get()));
617604
}
618605

619606
TypeRefPointer
620607
visitExistentialMetatypeTypeRef(const ExistentialMetatypeTypeRef *EM) {
621-
if (auto SubstitutedInstance = visit(EM->getInstanceType().get()))
622-
return MetatypeTypeRef::create(SubstitutedInstance);
623-
else
624-
return nullptr;
608+
assert(EM->getInstanceType()->isConcrete());
609+
return std::make_shared<ExistentialMetatypeTypeRef>(*EM);
625610
}
626611

627612
TypeRefPointer
628613
visitGenericTypeParameterTypeRef(const GenericTypeParameterTypeRef *GTP) {
629-
return Substitutions[{GTP->getDepth(), GTP->getIndex()}];
614+
auto found = Substitutions.find({GTP->getDepth(), GTP->getIndex()});
615+
assert(found != Substitutions.end());
616+
assert(found->second->isConcrete());
617+
return found->second;
630618
}
631619

632620
TypeRefPointer
633621
visitDependentMemberTypeRef(const DependentMemberTypeRef *DM) {
634622
auto SubstBase = visit(DM->getBase().get());
635-
if (!SubstBase || !SubstBase->isConcrete())
636-
return nullptr;
637623

638624
TypeRefPointer TypeWitness;
639625

@@ -649,12 +635,11 @@ class TypeRefSubstitution
649635
break;
650636
}
651637
default:
652-
return nullptr;
638+
assert(false && "Unknown base type");
653639
}
654-
if (!TypeWitness)
655-
return nullptr;
656640

657-
return visit(TypeWitness.get());
641+
assert(TypeWitness);
642+
return TypeWitness->subst(RC, SubstBase->getSubstMap());
658643
}
659644

660645
TypeRefPointer visitForeignClassTypeRef(const ForeignClassTypeRef *F) {
@@ -666,25 +651,16 @@ class TypeRefSubstitution
666651
}
667652

668653
TypeRefPointer visitUnownedStorageTypeRef(const UnownedStorageTypeRef *US) {
669-
if (auto SubstitutedType = visit(US->getType().get()))
670-
return UnownedStorageTypeRef::create(SubstitutedType);
671-
else
672-
return nullptr;
654+
return UnownedStorageTypeRef::create(visit(US->getType().get()));
673655
}
674656

675657
TypeRefPointer visitWeakStorageTypeRef(const WeakStorageTypeRef *WS) {
676-
if (auto SubstitutedType = visit(WS->getType().get()))
677-
return WeakStorageTypeRef::create(SubstitutedType);
678-
else
679-
return nullptr;
658+
return WeakStorageTypeRef::create(visit(WS->getType().get()));
680659
}
681660

682661
TypeRefPointer
683662
visitUnmanagedStorageTypeRef(const UnmanagedStorageTypeRef *US) {
684-
if (auto SubstitutedType = visit(US->getType().get()))
685-
return UnmanagedStorageTypeRef::create(SubstitutedType);
686-
else
687-
return nullptr;
663+
return UnmanagedStorageTypeRef::create(visit(US->getType().get()));
688664
}
689665

690666
TypeRefPointer visitOpaqueTypeRef(const OpaqueTypeRef *Op) {
@@ -695,7 +671,9 @@ class TypeRefSubstitution
695671
template <typename Runtime>
696672
TypeRefPointer
697673
TypeRef::subst(ReflectionContext<Runtime> &RC, GenericArgumentMap Subs) {
698-
return TypeRefSubstitution<Runtime>(RC, Subs).visit(this);
674+
TypeRefPointer Result = TypeRefSubstitution<Runtime>(RC, Subs).visit(this);
675+
assert(Result->isConcrete());
676+
return Result;
699677
}
700678

701679
} // end namespace reflection

0 commit comments

Comments
 (0)