Skip to content

Commit 4f0643c

Browse files
committed
Canonicalize the conforming type of BuiltinConformances.
It turns out they aren't always canonical by construction (and they don't really need to be), so we should canonicalize the type and requirements when we canonical a conformance ref. Fixes rdar://94877954.
1 parent 0464fd3 commit 4f0643c

File tree

2 files changed

+52
-3
lines changed

2 files changed

+52
-3
lines changed

lib/AST/ProtocolConformance.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,8 +1608,22 @@ bool ProtocolConformance::isCanonical() const {
16081608

16091609
switch (getKind()) {
16101610
case ProtocolConformanceKind::Self:
1611-
case ProtocolConformanceKind::Normal:
1611+
case ProtocolConformanceKind::Normal: {
1612+
return true;
1613+
}
16121614
case ProtocolConformanceKind::Builtin: {
1615+
// Check that the generic signature of the conformance is canonical.
1616+
auto builtinConformance = cast<BuiltinProtocolConformance>(this);
1617+
if (builtinConformance->getGenericSignature()
1618+
&& !builtinConformance->getGenericSignature()->isCanonical()) {
1619+
return false;
1620+
}
1621+
// Check that the satisfied conditional requirements are canonical.
1622+
for (auto &requirement : builtinConformance->getConditionalRequirements()) {
1623+
if (!requirement.isCanonical()) {
1624+
return false;
1625+
}
1626+
}
16131627
return true;
16141628
}
16151629
case ProtocolConformanceKind::Inherited: {
@@ -1638,11 +1652,25 @@ ProtocolConformance *ProtocolConformance::getCanonicalConformance() {
16381652

16391653
switch (getKind()) {
16401654
case ProtocolConformanceKind::Self:
1641-
case ProtocolConformanceKind::Normal:
1642-
case ProtocolConformanceKind::Builtin: {
1655+
case ProtocolConformanceKind::Normal: {
16431656
// Root conformances are always canonical by construction.
16441657
return this;
16451658
}
1659+
case ProtocolConformanceKind::Builtin: {
1660+
// Canonicalize the subject type of the builtin conformance.
1661+
auto &Ctx = getType()->getASTContext();
1662+
auto builtinConformance = cast<BuiltinProtocolConformance>(this);
1663+
SmallVector<Requirement, 4> canonicalRequirements;
1664+
for (auto &reqt : builtinConformance->getConditionalRequirements()) {
1665+
canonicalRequirements.push_back(reqt.getCanonical());
1666+
}
1667+
return Ctx.getBuiltinConformance(
1668+
builtinConformance->getType()->getCanonicalType(),
1669+
builtinConformance->getProtocol(),
1670+
builtinConformance->getGenericSignature().getCanonicalSignature(),
1671+
canonicalRequirements,
1672+
builtinConformance->getBuiltinConformanceKind());
1673+
}
16461674

16471675
case ProtocolConformanceKind::Inherited: {
16481676
auto &Ctx = getType()->getASTContext();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-swift-emit-silgen -disable-availability-checking -verify %s
2+
3+
// rdar://94877954
4+
5+
// `dynamic` prevents SILGen from lowering away
6+
// the opaque return type of `foo`
7+
dynamic func foo<T: Sendable>(f: () -> T) -> some Sendable {
8+
if #available(macOS 11.0, *) {
9+
return f()
10+
} else {
11+
return ()
12+
}
13+
}
14+
15+
func bar() {
16+
let x: Void = ()
17+
let y: () = ()
18+
var a = foo { x }
19+
a = foo { y }
20+
_ = a
21+
}

0 commit comments

Comments
 (0)