Skip to content

Commit 6b9d96a

Browse files
authored
Merge pull request #73771 from kavon/6.0-tilde-copyable-printing-interface-rdar126090425
[6.0🍒] ASTPrinter: handle inverses in compositions
2 parents ba7192b + 5c9ec49 commit 6b9d96a

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
@@ -7868,7 +7868,24 @@ swift::getInheritedForPrinting(
78687868
// Collect explicit inherited types.
78697869
for (auto i : inherited.getIndices()) {
78707870
if (auto ty = inherited.getResolvedType(i)) {
7871+
// Preserve inverses separately, because the `foundUnprintable` logic
7872+
// doesn't handle compositions with a mix of printable and unprintable
7873+
// types! That's handled later by `InheritedProtocolCollector`.
7874+
//
7875+
// Generally speaking, `getInheritedForPrinting` needs to be
7876+
// querying `InheritedProtocolCollector` to find out what protocols it
7877+
// should print in the inheritance clause, to reduce code duplication
7878+
// in the printer.
7879+
InvertibleProtocolSet printableInverses;
7880+
78717881
bool foundUnprintable = ty.findIf([&](Type subTy) {
7882+
{
7883+
// We canonicalize the composition to ensure no inverses are missed.
7884+
auto subCanTy = subTy->getCanonicalType();
7885+
if (auto PCT = subCanTy->getAs<ProtocolCompositionType>()) {
7886+
printableInverses.insertAll(PCT->getInverses());
7887+
}
7888+
}
78727889
if (auto aliasTy = dyn_cast<TypeAliasType>(subTy.getPointer()))
78737890
return !options.shouldPrint(aliasTy->getDecl());
78747891
if (auto NTD = subTy->getAnyNominal()) {
@@ -7877,8 +7894,22 @@ swift::getInheritedForPrinting(
78777894
}
78787895
return false;
78797896
});
7880-
if (foundUnprintable)
7897+
7898+
// Preserve any inverses that appeared in the unprintable type.
7899+
if (foundUnprintable) {
7900+
if (printableInverses.contains(InvertibleProtocolKind::Copyable)
7901+
&& options.SuppressNoncopyableGenerics)
7902+
printableInverses.remove(InvertibleProtocolKind::Copyable);
7903+
7904+
if (!printableInverses.empty()) {
7905+
auto inversesTy = ProtocolCompositionType::get(decl->getASTContext(),
7906+
/*members=*/{},
7907+
printableInverses,
7908+
/*anyObject=*/false);
7909+
Results.push_back(InheritedEntry(TypeLoc::withoutLoc(inversesTy)));
7910+
}
78817911
continue;
7912+
}
78827913

78837914
// Suppress Copyable and ~Copyable.
78847915
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)