Skip to content

Commit 64b8f61

Browse files
committed
AST: Account for protocol compositions and nested types in «findProtocolSelfReferences»
1 parent eb1bd07 commit 64b8f61

File tree

2 files changed

+61
-39
lines changed

2 files changed

+61
-39
lines changed

lib/AST/Decl.cpp

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5008,24 +5008,31 @@ findProtocolSelfReferences(const ProtocolDecl *proto, Type type,
50085008
return findProtocolSelfReferences(proto, selfType->getSelfType(), position);
50095009
}
50105010

5011-
// Most bound generic types are invariant.
5012-
if (auto *const bgt = type->getAs<BoundGenericType>()) {
5011+
if (auto *const nominal = type->getAs<NominalOrBoundGenericNominalType>()) {
50135012
auto info = SelfReferenceInfo();
50145013

5015-
if (bgt->isArray()) {
5016-
// Swift.Array preserves variance in its Value type.
5017-
info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().front(),
5018-
position);
5019-
} else if (bgt->isDictionary()) {
5020-
// Swift.Dictionary preserves variance in its Element type.
5021-
info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().front(),
5022-
SelfReferencePosition::Invariant);
5023-
info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().back(),
5024-
position);
5025-
} else {
5026-
for (auto paramType : bgt->getGenericArgs()) {
5027-
info |= findProtocolSelfReferences(proto, paramType,
5014+
// Don't forget to look in the parent.
5015+
if (const auto parent = nominal->getParent()) {
5016+
info |= findProtocolSelfReferences(proto, parent, position);
5017+
}
5018+
5019+
// Most bound generic types are invariant.
5020+
if (auto *const bgt = type->getAs<BoundGenericType>()) {
5021+
if (bgt->isArray()) {
5022+
// Swift.Array preserves variance in its Value type.
5023+
info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().front(),
5024+
position);
5025+
} else if (bgt->isDictionary()) {
5026+
// Swift.Dictionary preserves variance in its Element type.
5027+
info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().front(),
50285028
SelfReferencePosition::Invariant);
5029+
info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().back(),
5030+
position);
5031+
} else {
5032+
for (auto paramType : bgt->getGenericArgs()) {
5033+
info |= findProtocolSelfReferences(proto, paramType,
5034+
SelfReferencePosition::Invariant);
5035+
}
50295036
}
50305037
}
50315038

@@ -5037,6 +5044,16 @@ findProtocolSelfReferences(const ProtocolDecl *proto, Type type,
50375044
if (type->is<OpaqueTypeArchetypeType>())
50385045
return SelfReferenceInfo::forSelfRef(SelfReferencePosition::Invariant);
50395046

5047+
// Protocol compositions preserve variance.
5048+
if (auto *comp = type->getAs<ProtocolCompositionType>()) {
5049+
// 'Self' may be referenced only in a superclass component.
5050+
if (const auto superclass = comp->getSuperclass()) {
5051+
return findProtocolSelfReferences(proto, superclass, position);
5052+
}
5053+
5054+
return SelfReferenceInfo();
5055+
}
5056+
50405057
// A direct reference to 'Self'.
50415058
if (proto->getSelfInterfaceType()->isEqual(type))
50425059
return SelfReferenceInfo::forSelfRef(position);

test/decl/protocol/protocols_with_self_or_assoc_reqs.swift

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
struct G<T> {
88
class Inner {}
9+
struct InnerG<T> {}
910
}
1011
class C<T> {}
1112

@@ -57,6 +58,7 @@ protocol P1 {
5758
func invariantSelf8(_: G<(Self) -> Void>)
5859
func invariantSelf9(_: G<() -> Self>)
5960
func invariantSelf10(_: P1 & C<Self>)
61+
func invariantSelf11() -> G<Self>.InnerG<Void>
6062
func invariantAssoc1(_: inout Q)
6163
func invariantAssoc2(_: (inout Q) -> Void)
6264
func invariantAssoc3(_: inout Array<() -> Q>)
@@ -67,6 +69,7 @@ protocol P1 {
6769
func invariantAssoc8(_: G<(Q) -> Void>)
6870
func invariantAssoc9(_: G<() -> Q>)
6971
func invariantAssoc10(_: P1 & C<Q>)
72+
func invariantAssoc11() -> G<Q>.InnerG<Void>
7073

7174
// Properties
7275
var covariantSelfPropSimple: Self { get }
@@ -115,6 +118,7 @@ protocol P1 {
115118
var invariantSelfProp8: (G<(Self) -> Void>) -> Void { get }
116119
var invariantSelfProp9: (G<() -> Self>) -> Void { get }
117120
var invariantSelfProp10: (P1 & C<Self>) -> Void { get }
121+
var invariantSelfProp11: G<Self>.InnerG<Void> { get }
118122
var invariantAssocProp1: (inout Q) -> Void { get }
119123
var invariantAssocProp2: ((inout Q) -> Void) -> Void { get }
120124
var invariantAssocProp3: (inout Array<() -> Q>) -> Void { get }
@@ -125,6 +129,7 @@ protocol P1 {
125129
var invariantAssocProp8: (G<(Q) -> Void>) { get }
126130
var invariantAssocProp9: (G<() -> Q>) -> Void { get }
127131
var invariantAssocProp10: (P1 & C<Q>) -> Void { get }
132+
var invariantAssocProp11: G<Q>.InnerG<Void> { get }
128133

129134
// Subscripts
130135
subscript(covariantSelfSubscriptSimple _: Void) -> Self { get }
@@ -168,13 +173,15 @@ protocol P1 {
168173
subscript(invariantSelfSubscript5 _: G<(Self) -> Void>) -> Void { get }
169174
subscript(invariantSelfSubscript6 _: G<() -> Self>) -> Void { get }
170175
subscript(invariantSelfSubscript7 _: P1 & C<Self>) -> Void { get }
176+
subscript(invariantSelfSubscript8 _: Void) -> G<Self>.InnerG<Void> { get }
171177
subscript(invariantAssocSubscript1 _: G<Q>) -> Void { get }
172178
subscript(invariantAssocSubscript2 _: Void) -> G<Q> { get }
173179
subscript(invariantAssocSubscript3 _: Void) -> G<Q>.Inner { get }
174180
subscript(invariantAssocSubscript4 _: (G<Q>) -> Void) -> Void { get }
175181
subscript(invariantAssocSubscript5 _: G<(Q) -> Void>) -> Void { get }
176182
subscript(invariantAssocSubscript6 _: G<() -> Q>) -> Void { get }
177183
subscript(invariantAssocSubscript7 _: P1 & C<Q>) -> Void { get }
184+
subscript(invariantAssocSubscript8 _: Void) -> G<Q>.InnerG<Void> { get }
178185
}
179186
@available(macOS 10.15, *)
180187
extension P1 {
@@ -273,16 +280,16 @@ do {
273280
arg.invariantSelf4(0) // expected-error {{member 'invariantSelf4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
274281
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<P1>'}}
275282
arg.invariantSelf5() // expected-error {{member 'invariantSelf5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
276-
// FIXME: Should be diagnosed.
277-
// arg.invariantSelf6()
283+
arg.invariantSelf6() // expected-error {{member 'invariantSelf6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
278284
arg.invariantSelf7(0) // expected-error {{member 'invariantSelf7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
279285
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G<P1>) -> Void'}}
280286
arg.invariantSelf8(0) // expected-error {{member 'invariantSelf8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
281287
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1) -> Void>'}}
282288
arg.invariantSelf9(0) // expected-error {{member 'invariantSelf9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
283289
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1>'}}
284-
// FIXME: Should be diagnosed.
285-
// arg.invariantSelf10(0)
290+
arg.invariantSelf10(0) // expected-error {{member 'invariantSelf10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
291+
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'C<P1>'}}
292+
arg.invariantSelf11() // expected-error {{member 'invariantSelf11' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
286293
arg.invariantAssoc1(0) // expected-error {{member 'invariantAssoc1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
287294
// FIXME: Silence these since we cannot make use of the member anyway.
288295
// expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'P1.Q'}}
@@ -293,16 +300,16 @@ do {
293300
arg.invariantAssoc4(0) // expected-error {{member 'invariantAssoc4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
294301
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<P1.Q>'}}
295302
arg.invariantAssoc5() // expected-error {{member 'invariantAssoc5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
296-
// FIXME: Should be diagnosed.
297-
// arg.invariantAssoc6()
303+
arg.invariantAssoc6() // expected-error {{member 'invariantAssoc6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
298304
arg.invariantAssoc7(0) // expected-error {{member 'invariantAssoc7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
299305
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G<P1.Q>) -> Void'}}
300306
arg.invariantAssoc8(0) // expected-error {{member 'invariantAssoc8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
301307
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1.Q) -> Void>'}}
302308
arg.invariantAssoc9(0) // expected-error {{member 'invariantAssoc9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
303309
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1.Q>'}}
304-
// FIXME: Should be diagnosed.
305-
// arg.invariantAssoc10(0)
310+
arg.invariantAssoc10(0) // expected-error {{member 'invariantAssoc10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
311+
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'C<P1.Q>'}}
312+
arg.invariantAssoc11() // expected-error {{member 'invariantAssoc11' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
306313

307314
arg.contravariantSelfProp1 // expected-error {{member 'contravariantSelfProp1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
308315
arg.contravariantSelfProp2 // expected-error {{member 'contravariantSelfProp2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
@@ -333,25 +340,23 @@ do {
333340
arg.invariantSelfProp3 // expected-error {{member 'invariantSelfProp3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
334341
arg.invariantSelfProp4 // expected-error {{member 'invariantSelfProp4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
335342
arg.invariantSelfProp5 // expected-error {{member 'invariantSelfProp5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
336-
// FIXME: Should be diagnosed.
337-
// arg.invariantSelfProp6
343+
arg.invariantSelfProp6 // expected-error {{member 'invariantSelfProp6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
338344
arg.invariantSelfProp7 // expected-error {{member 'invariantSelfProp7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
339345
arg.invariantSelfProp8 // expected-error {{member 'invariantSelfProp8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
340346
arg.invariantSelfProp9 // expected-error {{member 'invariantSelfProp9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
341-
// FIXME: Should be diagnosed.
342-
// arg.invariantSelfProp10
347+
arg.invariantSelfProp10 // expected-error {{member 'invariantSelfProp10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
348+
arg.invariantSelfProp11 // expected-error {{member 'invariantSelfProp11' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
343349
arg.invariantAssocProp1 // expected-error {{member 'invariantAssocProp1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
344350
arg.invariantAssocProp2 // expected-error {{member 'invariantAssocProp2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
345351
arg.invariantAssocProp3 // expected-error {{member 'invariantAssocProp3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
346352
arg.invariantAssocProp4 // expected-error {{member 'invariantAssocProp4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
347353
arg.invariantAssocProp5 // expected-error {{member 'invariantAssocProp5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
348-
// FIXME: Should be diagnosed.
349-
// arg.invariantAssocProp6
354+
arg.invariantAssocProp6 // expected-error {{member 'invariantAssocProp6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
350355
arg.invariantAssocProp7 // expected-error {{member 'invariantAssocProp7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
351356
arg.invariantAssocProp8 // expected-error {{member 'invariantAssocProp8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
352357
arg.invariantAssocProp9 // expected-error {{member 'invariantAssocProp9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
353-
// FIXME: Should be diagnosed.
354-
// arg.invariantAssocProp10
358+
arg.invariantAssocProp10 // expected-error {{member 'invariantAssocProp10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
359+
arg.invariantAssocProp11 // expected-error {{member 'invariantAssocProp11' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
355360

356361
arg[contravariantSelfSubscript1: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
357362
// FIXME: Silence these since we cannot make use of the member anyway.
@@ -394,30 +399,30 @@ do {
394399
// FIXME: Silence these since we cannot make use of the member anyway.
395400
// expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'G<P1>'}}
396401
arg[invariantSelfSubscript2: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
397-
// FIXME: Should be diagnosed.
398-
// arg[invariantSelfSubscript3: ()]
402+
arg[invariantSelfSubscript3: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
399403
arg[invariantSelfSubscript4: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
400404
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G<P1>) -> Void'}}
401405
arg[invariantSelfSubscript5: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
402406
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1) -> Void>'}}
403407
arg[invariantSelfSubscript6: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
404408
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1>'}}
405-
// FIXME: Should be diagnosed.
406-
// arg[invariantSelfSubscript7: 0]
409+
arg[invariantSelfSubscript7: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
410+
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'C<P1>'}}
411+
arg[invariantSelfSubscript8: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
407412
arg[invariantAssocSubscript1: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
408413
// FIXME: Silence these since we cannot make use of the member anyway.
409414
// expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'G<P1.Q>'}}
410415
arg[invariantAssocSubscript2: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
411-
// FIXME: Should be diagnosed.
412-
// arg[invariantAssocSubscript3: ()]
416+
arg[invariantAssocSubscript3: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
413417
arg[invariantAssocSubscript4: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
414418
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G<P1.Q>) -> Void'}}
415419
arg[invariantAssocSubscript5: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
416420
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1.Q) -> Void>'}}
417421
arg[invariantAssocSubscript6: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
418422
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1.Q>'}}
419-
// FIXME: Should be diagnosed.
420-
// arg[invariantAssocSubscript7: 0]
423+
arg[invariantAssocSubscript7: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
424+
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'C<P1.Q>'}}
425+
arg[invariantAssocSubscript8: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
421426
}
422427
}
423428

0 commit comments

Comments
 (0)