Skip to content

Commit 5492690

Browse files
committed
Fix archetype access path binding
When considering a type that declares an archetype bound to an associated type, we were not generating the access paths to any underlying conformance data and so were not properly able to grab the witness table for those conformances resulting in a crash. This way, all bound requirements also make sure to bind archetype access paths so we can see actually see the conformances.
1 parent 4fb66a1 commit 5492690

File tree

3 files changed

+65
-49
lines changed

3 files changed

+65
-49
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 59 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,32 +1669,39 @@ bool irgen::hasPolymorphicParameters(CanSILFunctionType ty) {
16691669
}
16701670
}
16711671

1672-
/// Emit a polymorphic parameters clause, binding all the metadata necessary.
1673-
void EmitPolymorphicParameters::emit(Explosion &in,
1674-
WitnessMetadata *witnessMetadata,
1675-
const GetParameterFn &getParameter) {
1676-
// Collect any early sources and bind local type data from them.
1677-
for (const Source &source : getSources()) {
1678-
bindExtraSource(source, in, witnessMetadata);
1679-
}
1672+
static
1673+
void addPotentialArchetypeAccessPath(IRGenFunction &IGF,
1674+
CanType targetDepType,
1675+
CanType sourceDepType,
1676+
GetTypeParameterInContextFn getInContext) {
1677+
assert(targetDepType->isTypeParameter());
1678+
assert(sourceDepType->isTypeParameter());
16801679

1681-
// Collect any concrete type metadata that's been passed separately.
1682-
enumerateUnfulfilledRequirements([&](GenericRequirement requirement) {
1683-
auto value = in.claimNext();
1684-
bindGenericRequirement(IGF, requirement, value,
1685-
[&](CanType type) { return getTypeInContext(type);});
1686-
});
1680+
// We can only break down an associated-type path.
1681+
auto sourceDepMemberType = dyn_cast<DependentMemberType>(sourceDepType);
1682+
if (!sourceDepMemberType) return;
16871683

1688-
// Bind all the fulfillments we can from the formal parameters.
1689-
bindParameterSources(getParameter);
1684+
// We only really need to do this when there's a non-trivial set of
1685+
// conformances, but we can't determine that just from this decl:
1686+
// the associated type might gain conformances in a refining protocol.
1687+
auto association = sourceDepMemberType->getAssocType();
16901688

1691-
// Bind all the archetype access paths.
1692-
bindArchetypeAccessPaths();
1693-
}
1689+
// These can end up as non-archetypes because of multiple levels of
1690+
// equality.
1691+
auto destArchetype =
1692+
dyn_cast<ArchetypeType>(getInContext(targetDepType));
1693+
if (!destArchetype) return;
1694+
auto srcBaseArchetype =
1695+
dyn_cast<ArchetypeType>(getInContext(sourceDepMemberType.getBase()));
1696+
if (!srcBaseArchetype) return;
16941697

1695-
void EmitPolymorphicParameters::bindArchetypeAccessPaths() {
1696-
if (!Generics) return;
1698+
IGF.addArchetypeAccessPath(destArchetype,
1699+
{srcBaseArchetype, association});
1700+
}
16971701

1702+
static void bindArchetypeAccessPaths(IRGenFunction &IGF,
1703+
GenericSignature *Generics,
1704+
GetTypeParameterInContextFn getInContext) {
16981705
// Remember all the extra ways we have of reaching the parameter
16991706
// archetypes due to type equality constraints.
17001707
for (auto reqt : Generics->getRequirements()) {
@@ -1710,36 +1717,37 @@ void EmitPolymorphicParameters::bindArchetypeAccessPaths() {
17101717
auto firstType = reqt.getFirstType()->getCanonicalType();
17111718
auto secondType = reqt.getSecondType()->getCanonicalType();
17121719

1713-
addPotentialArchetypeAccessPath(firstType, secondType);
1714-
addPotentialArchetypeAccessPath(secondType, firstType);
1720+
addPotentialArchetypeAccessPath(IGF, firstType, secondType, getInContext);
1721+
addPotentialArchetypeAccessPath(IGF, secondType, firstType, getInContext);
17151722
}
17161723
}
17171724

1718-
void EmitPolymorphicParameters::
1719-
addPotentialArchetypeAccessPath(CanType targetDepType, CanType sourceDepType) {
1720-
assert(targetDepType->isTypeParameter());
1721-
assert(sourceDepType->isTypeParameter());
1722-
1723-
// We can only break down an associated-type path.
1724-
auto sourceDepMemberType = dyn_cast<DependentMemberType>(sourceDepType);
1725-
if (!sourceDepMemberType) return;
1725+
/// Emit a polymorphic parameters clause, binding all the metadata necessary.
1726+
void EmitPolymorphicParameters::emit(Explosion &in,
1727+
WitnessMetadata *witnessMetadata,
1728+
const GetParameterFn &getParameter) {
1729+
// Collect any early sources and bind local type data from them.
1730+
for (const Source &source : getSources()) {
1731+
bindExtraSource(source, in, witnessMetadata);
1732+
}
1733+
1734+
auto getInContext = [&](CanType type) -> CanType {
1735+
return getTypeInContext(type);
1736+
};
17261737

1727-
// We only really need to do this when there's a non-trivial set of
1728-
// conformances, but we can't determine that just from this decl:
1729-
// the associated type might gain conformances in a refining protocol.
1730-
auto association = sourceDepMemberType->getAssocType();
1738+
// Collect any concrete type metadata that's been passed separately.
1739+
enumerateUnfulfilledRequirements([&](GenericRequirement requirement) {
1740+
auto value = in.claimNext();
1741+
bindGenericRequirement(IGF, requirement, value, getInContext);
1742+
});
17311743

1732-
// These can end up as non-archetypes because of multiple levels of
1733-
// equality.
1734-
auto destArchetype =
1735-
dyn_cast<ArchetypeType>(getTypeInContext(targetDepType));
1736-
if (!destArchetype) return;
1737-
auto srcBaseArchetype =
1738-
dyn_cast<ArchetypeType>(getTypeInContext(sourceDepMemberType.getBase()));
1739-
if (!srcBaseArchetype) return;
1744+
// Bind all the fulfillments we can from the formal parameters.
1745+
bindParameterSources(getParameter);
17401746

1741-
IGF.addArchetypeAccessPath(destArchetype,
1742-
{srcBaseArchetype, association});
1747+
if (!Generics) return;
1748+
1749+
// Bind all the archetype access paths.
1750+
bindArchetypeAccessPaths(IGF, Generics, getInContext);
17431751
}
17441752

17451753
void IRGenFunction::addArchetypeAccessPath(CanArchetypeType targetArchetype,
@@ -2507,6 +2515,12 @@ void GenericTypeRequirements::bindFromBuffer(IRGenFunction &IGF,
25072515
Address buffer,
25082516
GetTypeParameterInContextFn getInContext) {
25092517
bindFromGenericRequirementsBuffer(IGF, Requirements, buffer, getInContext);
2518+
2519+
auto Generics = TheDecl->getGenericSignature();
2520+
if (!Generics) return;
2521+
2522+
// Bind all the archetype access paths in the signature's requirements.
2523+
bindArchetypeAccessPaths(IGF, Generics, getInContext);
25102524
}
25112525

25122526
void irgen::bindFromGenericRequirementsBuffer(IRGenFunction &IGF,

lib/IRGen/GenProto.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,6 @@ namespace irgen {
331331
// Did the convention decide that the parameter at the given index
332332
// was a class-pointer source?
333333
bool isClassPointerSource(unsigned paramIndex);
334-
335-
void bindArchetypeAccessPaths();
336-
void addPotentialArchetypeAccessPath(CanType targetDepType,
337-
CanType sourceDepType);
338334
};
339335

340336
} // end namespace irgen

test/IRGen/same_type_constraints.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,9 @@ public extension P where Foo == DefaultFoo<Self> {
1616
}
1717

1818
// CHECK: define{{( protected)?}} void @_TFe21same_type_constraintsRxS_1Pwx3FoozGVS_10DefaultFoox_rS0_3foofT_GS2_x_
19+
20+
// <rdar://26873036> IRGen crash with derived class declaring same-type constraint on constrained associatedtype.
21+
public class C1<T: Equatable> { }
22+
public class C2<T: Equatable, U: P where T == U.Foo>: C1<T> {}
23+
24+
// CHECK: define{{( protected)?}} void @_TFC21same_type_constraints2C1D

0 commit comments

Comments
 (0)