NCGenerics: break cycle with SuperclassTypeRequest

With NoncopyableGenerics, we get a cycle involving
`SuperclassTypeRequest` with this program:

  public struct RawMarkupHeader {}
  final class RawMarkup: ManagedBuffer<RawMarkupHeader, RawMarkup> { }

Because we generally don't support the following kind of relationship:

  class Base<T: P>: P {}
  class Derived: Base<Derived> {}

This commit works around the root-cause, which is that Derived's
synthesized conformance to Copyable gets superceded by the inherited one
from Base. Instead of recording conformances in the ConformanceLookup
table at all, create builtin conformances on the fly, since classes
cannot be conditionally Copyable or Escapable.
This commit is contained in:
Kavon Farvardin
2024-02-12 21:32:31 -08:00
parent 98e6c7b935
commit 3a45393e17
7 changed files with 123 additions and 43 deletions

View File

@@ -102,9 +102,10 @@ switch (getKind()) { \
return cast<NormalProtocolConformance>(this)->Method Args; \
case ProtocolConformanceKind::Self: \
return cast<SelfProtocolConformance>(this)->Method Args; \
case ProtocolConformanceKind::Builtin: \
return cast<BuiltinProtocolConformance>(this)->Method Args; \
case ProtocolConformanceKind::Specialized: \
case ProtocolConformanceKind::Inherited: \
case ProtocolConformanceKind::Builtin: \
llvm_unreachable("not a root conformance"); \
} \
llvm_unreachable("bad ProtocolConformanceKind");
@@ -1090,19 +1091,21 @@ void NominalTypeDecl::prepareConformanceTable() const {
// Synthesize the unconditional conformances to invertible protocols.
// For conditional ones, see findSynthesizedConformances .
if (ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics)) {
bool missingOne = false;
for (auto ip : InvertibleProtocolSet::full()) {
auto invertible = getMarking(ip);
if (!invertible.getInverse() || bool(invertible.getPositive()))
addSynthesized(ctx.getProtocol(getKnownProtocolKind(ip)));
else
missingOne = true;
// Classes get their conformances during ModuleDecl::lookupConformance.
if (!isa<ClassDecl>(this)) {
bool missingOne = false;
for (auto ip : InvertibleProtocolSet::full()) {
auto invertible = getMarking(ip);
if (!invertible.getInverse() || bool(invertible.getPositive()))
addSynthesized(ctx.getProtocol(getKnownProtocolKind(ip)));
else
missingOne = true;
}
// FIXME: rdar://122289155 (NCGenerics: convert Equatable, Hashable, and RawRepresentable to ~Copyable.)
if (missingOne)
return;
}
// FIXME: rdar://122289155 (NCGenerics: convert Equatable, Hashable, and RawRepresentable to ~Copyable.)
if (missingOne)
return;
} else if (!canBeCopyable()) {
return; // No synthesized conformances for move-only nominals.
}