Skip to content

Commit 2141eac

Browse files
authored
Merge pull request #3093 from CodaFi/witness-protection-program
[SR-1813] Fix archetype access path binding
2 parents ad559f9 + 5492690 commit 2141eac

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)