Skip to content

Commit 6e25d8b

Browse files
authored
Merge pull request #73770 from kavon/tilde-copyable-printing-interface-rdar126090425
ASTPrinter: handle inverses in compositions
2 parents 231f5b5 + 210cfb2 commit 6e25d8b

File tree

3 files changed

+67
-1
lines changed

3 files changed

+67
-1
lines changed

lib/AST/ASTPrinter.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7862,7 +7862,24 @@ swift::getInheritedForPrinting(
78627862
// Collect explicit inherited types.
78637863
for (auto i : inherited.getIndices()) {
78647864
if (auto ty = inherited.getResolvedType(i)) {
7865+
// Preserve inverses separately, because the `foundUnprintable` logic
7866+
// doesn't handle compositions with a mix of printable and unprintable
7867+
// types! That's handled later by `InheritedProtocolCollector`.
7868+
//
7869+
// Generally speaking, `getInheritedForPrinting` needs to be
7870+
// querying `InheritedProtocolCollector` to find out what protocols it
7871+
// should print in the inheritance clause, to reduce code duplication
7872+
// in the printer.
7873+
InvertibleProtocolSet printableInverses;
7874+
78657875
bool foundUnprintable = ty.findIf([&](Type subTy) {
7876+
{
7877+
// We canonicalize the composition to ensure no inverses are missed.
7878+
auto subCanTy = subTy->getCanonicalType();
7879+
if (auto PCT = subCanTy->getAs<ProtocolCompositionType>()) {
7880+
printableInverses.insertAll(PCT->getInverses());
7881+
}
7882+
}
78667883
if (auto aliasTy = dyn_cast<TypeAliasType>(subTy.getPointer()))
78677884
return !options.shouldPrint(aliasTy->getDecl());
78687885
if (auto NTD = subTy->getAnyNominal()) {
@@ -7871,8 +7888,22 @@ swift::getInheritedForPrinting(
78717888
}
78727889
return false;
78737890
});
7874-
if (foundUnprintable)
7891+
7892+
// Preserve any inverses that appeared in the unprintable type.
7893+
if (foundUnprintable) {
7894+
if (printableInverses.contains(InvertibleProtocolKind::Copyable)
7895+
&& options.SuppressNoncopyableGenerics)
7896+
printableInverses.remove(InvertibleProtocolKind::Copyable);
7897+
7898+
if (!printableInverses.empty()) {
7899+
auto inversesTy = ProtocolCompositionType::get(decl->getASTContext(),
7900+
/*members=*/{},
7901+
printableInverses,
7902+
/*anyObject=*/false);
7903+
Results.push_back(InheritedEntry(TypeLoc::withoutLoc(inversesTy)));
7904+
}
78757905
continue;
7906+
}
78767907

78777908
// Suppress Copyable and ~Copyable.
78787909
if (options.SuppressNoncopyableGenerics) {

test/ModuleInterface/Inputs/NoncopyableGenerics_Misc.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,13 @@ public func substCopyable(_ t: String?) {}
127127
public func substGenericCopyable<T>(_ t: T?) {}
128128
public func substNC(_ t: borrowing NoCopyPls?) {}
129129
public func substGenericNC<T: ~Copyable>(_ t: borrowing T?) {}
130+
131+
// coverage for rdar://126090425
132+
protocol P : ~Copyable {} // NOTE: it's important that this is NOT public.
133+
protocol Q: ~Copyable {} // NOTE: it's important that this is NOT public.
134+
public protocol Publik: ~Copyable {}
135+
public struct Concrete : (P & ~Copyable) {}
136+
public struct Generic<T: Publik & ~Copyable> : (P & ~Copyable) {}
137+
public struct VeryNested: (P & (Q & ~Copyable & Publik) & (P & ~Copyable)) {}
138+
public struct Twice: P & ~Copyable, Q & ~Copyable {}
139+
public struct RegularTwice: ~Copyable, ~Copyable {}

test/ModuleInterface/noncopyable_generics.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,31 @@ import NoncopyableGenerics_Misc
192192
// CHECK-MISC-NEXT: public func substGenericNC<T>(_ t: borrowing T?)
193193
// CHECK-MISC-NEXT: #endif
194194

195+
// CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics
196+
// CHECK-MISC-NEXT: public protocol Publik : ~Copyable {
197+
// CHECK-MISC-NEXT: }
198+
// CHECK-MISC-NEXT: #else
199+
// CHECK-MISC-NEXT: public protocol Publik {
200+
// CHECK-MISC-NEXT: }
201+
// CHECK-MISC-NEXT: #endif
202+
// CHECK-MISC-NEXT: public struct Concrete : ~Copyable {
203+
// CHECK-MISC-NEXT: }
204+
// CHECK-MISC-NEXT: #if compiler(>=5.3) && $NoncopyableGenerics
205+
// CHECK-MISC-NEXT: public struct Generic<T> : ~Copyable where T : {{.*}}.Publik, T : ~Copyable {
206+
// CHECK-MISC-NEXT: }
207+
// CHECK-MISC-NEXT: #else
208+
// CHECK-MISC-NEXT: public struct Generic<T> where T : {{.*}}.Publik {
209+
// CHECK-MISC-NEXT: }
210+
// CHECK-MISC-NEXT: #endif
211+
// CHECK-MISC-NEXT: public struct VeryNested : ~Copyable {
212+
// CHECK-MISC-NEXT: }
213+
// CHECK-MISC-NEXT: public struct Twice : ~Copyable, ~Copyable {
214+
// CHECK-MISC-NEXT: }
215+
// CHECK-MISC-NEXT: public struct RegularTwice : ~Swift.Copyable, ~Swift.Copyable {
216+
// CHECK-MISC-NEXT: }
217+
218+
// NOTE: below are extensions emitted at the end of NoncopyableGenerics_Misc.swift
219+
// CHECK-MISC: extension {{.*}}.VeryNested : {{.*}}.Publik {}
195220

196221
import Swiftskell
197222

0 commit comments

Comments
 (0)