Skip to content

Commit 1cf0345

Browse files
Merge pull request #58604 from AnthonyLatsis/5.7-min-comp-fix
🍒 [5.7] AST: Fix bug in subclass composition minimization
2 parents e905322 + f0aedd0 commit 1cf0345

File tree

2 files changed

+24
-9
lines changed

2 files changed

+24
-9
lines changed

lib/AST/Type.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4115,7 +4115,6 @@ CanType ProtocolCompositionType::getMinimalCanonicalType(
41154115
return Reqs.front().getSecondType()->getCanonicalType();
41164116
}
41174117

4118-
Type superclass;
41194118
llvm::SmallVector<Type, 2> MinimalMembers;
41204119
bool MinimalHasExplicitAnyObject = false;
41214120
auto ifaceTy = Sig.getGenericParams().back();
@@ -4126,10 +4125,6 @@ CanType ProtocolCompositionType::getMinimalCanonicalType(
41264125

41274126
switch (Req.getKind()) {
41284127
case RequirementKind::Superclass:
4129-
assert((!superclass || superclass->isEqual(Req.getSecondType()))
4130-
&& "Multiple distinct superclass constraints!");
4131-
superclass = Req.getSecondType();
4132-
break;
41334128
case RequirementKind::Conformance:
41344129
MinimalMembers.push_back(Req.getSecondType());
41354130
break;
@@ -4141,10 +4136,16 @@ CanType ProtocolCompositionType::getMinimalCanonicalType(
41414136
}
41424137
}
41434138

4144-
// Ensure superclass bounds appear first regardless of their order among
4145-
// the signature's requirements.
4146-
if (superclass)
4147-
MinimalMembers.insert(MinimalMembers.begin(), superclass->getCanonicalType());
4139+
// A superclass constraint is always retained and must appear first in the
4140+
// members list.
4141+
assert(Composition->getMembers().front()->getClassOrBoundGenericClass() ==
4142+
MinimalMembers.front()->getClassOrBoundGenericClass());
4143+
4144+
// If we are left with a single member and no layout constraint, the member
4145+
// is the minimal type. Also, note that a protocol composition cannot be
4146+
// constructed with a single member unless there is a layout constraint.
4147+
if (MinimalMembers.size() == 1 && !MinimalHasExplicitAnyObject)
4148+
return CanType(MinimalMembers.front());
41484149

41494150
// The resulting composition is necessarily canonical.
41504151
return CanType(build(Ctx, MinimalMembers, MinimalHasExplicitAnyObject));

test/type/subclass_composition.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ typealias OtherAndP2 = Other & P2
4242

4343
protocol P3 : class {}
4444

45+
protocol P4 {}
46+
4547
struct Unrelated {}
4648

4749
//
@@ -70,6 +72,18 @@ func alreadyConforms(_: P3 & AnyObject) {} // expected-error {{invalid redeclara
7072
func alreadyConformsMeta(_: P3.Type) {} // expected-note {{'alreadyConformsMeta' previously declared here}}
7173
func alreadyConformsMeta(_: (P3 & AnyObject).Type) {} // expected-error {{invalid redeclaration of 'alreadyConformsMeta'}}
7274

75+
func notARedeclaration(_: P4) {}
76+
func notARedeclaration(_: P4 & AnyObject) {}
77+
78+
do {
79+
class C: P4 {}
80+
struct S<T: P4> {
81+
// Don't crash when computing minimal compositions inside a generic context.
82+
func redeclaration(_: C & P4) {} // expected-note {{'redeclaration' previously declared here}}
83+
func redeclaration(_: C & P4) {} // expected-error {{invalid redeclaration of 'redeclaration'}}
84+
}
85+
}
86+
7387
// SE-0156 stipulates that a composition can contain multiple classes, as long
7488
// as they are all the same.
7589
func basicDiagnostics(

0 commit comments

Comments
 (0)