mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
ModuleInterface: Avoid printing generic arguments of a ParameterizedProtocolType in inheritance clause
When emitting module interfaces, parameterized protocols in inheritance clauses were being printed with generic arguments (public struct T: Fancy<Float64>), causing errors with protocol conformance verification. The fix strip ParameterizedProtocolType to its base protocol type when printing inherited types, producing the correct inheritance clause. Resolves: rdar://161925627
This commit is contained in:
@@ -8247,6 +8247,39 @@ static void getSyntacticInheritanceClause(const ProtocolDecl *proto,
|
||||
}
|
||||
}
|
||||
|
||||
static Type stripParameterizedProtocolArgs(Type type) {
|
||||
if (!type)
|
||||
return type;
|
||||
|
||||
// For each ParameterizedProtocolType process each member recursively
|
||||
if (auto *compositionType = type->getAs<ProtocolCompositionType>()) {
|
||||
SmallVector<Type, 4> processedMembers;
|
||||
bool hasChanged = false;
|
||||
for (auto member : compositionType->getMembers()) {
|
||||
Type processedMember = stripParameterizedProtocolArgs(member);
|
||||
if (!processedMember)
|
||||
continue;
|
||||
processedMembers.push_back(processedMember);
|
||||
if (processedMember.getPointer() != member.getPointer())
|
||||
hasChanged = true;
|
||||
}
|
||||
// Rebuild ProtocolCompositionType if at least one member had generic args
|
||||
if (hasChanged) {
|
||||
return ProtocolCompositionType::get(
|
||||
type->getASTContext(), processedMembers,
|
||||
compositionType->getInverses(),
|
||||
compositionType->hasExplicitAnyObject());
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
// Strip generic arguments of a single ParameterizedProtocolType
|
||||
if (auto *paramProto = type->getAs<ParameterizedProtocolType>()) {
|
||||
return paramProto->getBaseType();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
void
|
||||
swift::getInheritedForPrinting(
|
||||
const Decl *decl, const PrintOptions &options,
|
||||
@@ -8316,7 +8349,16 @@ swift::getInheritedForPrinting(
|
||||
}
|
||||
}
|
||||
|
||||
Results.push_back(inherited.getEntry(i));
|
||||
auto entry = inherited.getEntry(i);
|
||||
if (auto type = entry.getType()) {
|
||||
Type strippedType = stripParameterizedProtocolArgs(type);
|
||||
if (strippedType.getPointer() != type.getPointer()) {
|
||||
entry = InheritedEntry(TypeLoc::withoutLoc(strippedType),
|
||||
entry.getOptions());
|
||||
}
|
||||
}
|
||||
|
||||
Results.push_back(entry);
|
||||
}
|
||||
|
||||
// Collect synthesized conformances.
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
// RUN: %target-swift-emit-module-interface(%t/Fancy.swiftinterface) %s -module-name Library
|
||||
// RUN: %target-swift-typecheck-module-from-interface(%t/Fancy.swiftinterface) -module-name Library
|
||||
// RUN: %FileCheck %s < %t/Fancy.swiftinterface
|
||||
|
||||
public protocol Fancy<Stuff> {
|
||||
associatedtype Stuff
|
||||
}
|
||||
|
||||
// CHECK: public struct T : Library.Fancy {
|
||||
// CHECK: public typealias Stuff = Swift.Float64
|
||||
public struct T: Fancy<Float64> {
|
||||
}
|
||||
|
||||
public protocol Q {
|
||||
}
|
||||
|
||||
// CHECK: public struct S : Library.Fancy & Library.Q {
|
||||
// CHECK: public typealias Stuff = Swift.Int
|
||||
public struct S: Fancy<Int> & Q {
|
||||
}
|
||||
|
||||
public protocol P {
|
||||
}
|
||||
|
||||
// CHECK: public struct V : Library.Fancy & Library.P & Library.Q {
|
||||
// CHECK: public typealias Stuff = Swift.CChar32
|
||||
public struct V: ((Fancy<CChar32> & P) & Q) {
|
||||
}
|
||||
|
||||
public protocol Bar<T> {
|
||||
associatedtype T
|
||||
}
|
||||
|
||||
// CHECK: public struct X : Library.Bar & Library.Fancy
|
||||
// CHECK: public typealias Stuff = Swift.CChar32
|
||||
// CHECK: public typealias T = Swift.Int
|
||||
public struct X: Fancy<CChar32> & Bar<Int> {
|
||||
}
|
||||
|
||||
public class Base {
|
||||
}
|
||||
|
||||
public protocol B<A>: ~Copyable {
|
||||
associatedtype A
|
||||
}
|
||||
|
||||
// CHECK: public class Derived : Library.Base & Library.B {
|
||||
// CHECK: public typealias A = Swift.Int
|
||||
public class Derived: Base & B<Int> {
|
||||
}
|
||||
|
||||
public protocol R<E>: ~Copyable & ~Escapable {
|
||||
associatedtype E
|
||||
}
|
||||
|
||||
// CHECK: public struct N : Library.B & Library.R & ~Copyable {
|
||||
// CHECK: public typealias A = Swift.Float64
|
||||
// CHECK: public typealias E = Swift.Int
|
||||
public struct N: R<Int> & B<Float64> & ~Copyable {
|
||||
}
|
||||
Reference in New Issue
Block a user