Skip to content

Commit 51e03a7

Browse files
authored
Merge pull request #85148 from tshortli/suppress-inherited-retroactive-conformance-diags-with-module-qualification
Sema: Fix a regression in retroactive conformance diagnostic suppression
2 parents af86ce4 + 65a3b88 commit 51e03a7

File tree

2 files changed

+46
-22
lines changed

2 files changed

+46
-22
lines changed

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,30 +1720,35 @@ static TypeRepr *unwrapAttributedRepr(TypeRepr *repr) {
17201720
return repr;
17211721
}
17221722

1723+
struct ProtocolAndRetroactiveStatus {
1724+
ProtocolDecl *proto = nullptr;
1725+
bool isMarkedRetroactive = false;
1726+
};
1727+
17231728
static void collectProtocolsFromInheritedEntry(
1724-
const InheritedEntry &entry,
1725-
Type inheritedTy,
1726-
llvm::SmallPtrSetImpl<ProtocolDecl *> &protocolsWithRetroactiveAttr,
1727-
SmallVectorImpl<ProtocolDecl *> &protos) {
1729+
const InheritedEntry &entry, Type inheritedTy,
1730+
SmallVectorImpl<ProtocolAndRetroactiveStatus> &protos) {
1731+
1732+
bool isMarkedRetroactive = entry.isRetroactive();
17281733

17291734
if (auto *protoTy = inheritedTy->getAs<ProtocolType>()) {
17301735
auto *proto = protoTy->getDecl();
17311736

17321737
// As a fallback, to support previous language versions, also allow
17331738
// this through if the protocol has been explicitly module-qualified.
17341739
TypeRepr *repr = unwrapAttributedRepr(entry.getTypeRepr());
1735-
if (isModuleQualified(repr, proto->getParentModule())) {
1736-
protocolsWithRetroactiveAttr.insert(proto);
1737-
}
1740+
if (isModuleQualified(repr, proto->getParentModule()))
1741+
isMarkedRetroactive = true;
17381742

1739-
protos.push_back(proto);
1743+
protos.push_back({proto, isMarkedRetroactive});
17401744
} else if (auto *pct = inheritedTy->getAs<ProtocolCompositionType>()) {
17411745
for (auto member : pct->getMembers()) {
1742-
collectProtocolsFromInheritedEntry(entry, member,
1743-
protocolsWithRetroactiveAttr, protos);
1746+
// FIXME: Check for module qualification on each composed protocol.
1747+
collectProtocolsFromInheritedEntry(entry, member, protos);
17441748
}
17451749
} else if (auto *ppt = inheritedTy->getAs<ParameterizedProtocolType>()) {
1746-
protos.push_back(ppt->getProtocol());
1750+
// FIXME: Check for module qualification.
1751+
protos.push_back({ppt->getProtocol(), isMarkedRetroactive});
17471752
}
17481753
}
17491754

@@ -1810,11 +1815,12 @@ static void diagnoseRetroactiveConformances(
18101815
continue;
18111816
}
18121817

1813-
SmallVector<ProtocolDecl *, 2> protos;
1814-
collectProtocolsFromInheritedEntry(entry, inheritedTy,
1815-
protocolsWithRetroactiveAttr, protos);
1818+
SmallVector<ProtocolAndRetroactiveStatus, 2> protosAndStatuses;
1819+
collectProtocolsFromInheritedEntry(entry, inheritedTy, protosAndStatuses);
1820+
1821+
for (auto protoAndStatus : protosAndStatuses) {
1822+
auto proto = protoAndStatus.proto;
18161823

1817-
for (auto *proto : protos) {
18181824
proto->walkInheritedProtocols([&](ProtocolDecl *decl) {
18191825
// If this isn't a retroactive conformance, skip it.
18201826
auto found = protocols.find(proto);
@@ -1846,8 +1852,7 @@ static void diagnoseRetroactiveConformances(
18461852
return TypeWalker::Action::Continue;
18471853
}
18481854

1849-
// If it's marked @retroactive, no need to warn.
1850-
if (entry.isRetroactive()) {
1855+
if (protoAndStatus.isMarkedRetroactive) {
18511856
// Note that we encountered this protocol through a conformance marked
18521857
// @retroactive in case multiple clauses cause the protocol to be
18531858
// inherited.

test/Sema/extension_retroactive_conformances.swift

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,20 @@ public struct Sample3 {}
2424
public struct Sample4 {}
2525
public struct Sample5 {}
2626
public struct Sample6 {}
27+
public struct Sample6a {}
28+
public struct Sample6b {}
29+
public struct Sample6c {}
2730
public struct Sample7 {}
2831
public struct Sample8 {}
32+
public struct Sample8a {}
2933

3034
public struct SampleAlreadyConforms: SampleProtocol1 {}
3135

3236
public struct GenericSample1<T> {}
3337

3438
public struct Sample9 {}
35-
public struct Sample10 {}
39+
public struct Sample9a {}
40+
public struct Sample9b {}
3641

3742
#else
3843

@@ -83,9 +88,13 @@ typealias MySample6 = Sample6
8388
extension MySample6: SampleProtocol1 {} // expected-warning {{extension declares a conformance of imported type 'Sample6' to imported protocol 'SampleProtocol1'}}
8489
// expected-note @-1 {{add '@retroactive' to silence this warning}} {{22-37=@retroactive SampleProtocol1}}
8590

86-
// Ensure module-qualifying both types still silences the warning
91+
// Ensure module-qualifying the protocol silences the warning
8792

88-
extension Library.Sample6: Library.SampleProtocol2 {} // ok, module-qualified.
93+
extension Library.Sample6: Library.SampleProtocol2 {} // ok, both types are module-qualified.
94+
extension Sample6a: Library.SampleProtocol2 {} // ok, protocol is module qualified.
95+
extension Library.Sample6b: SampleProtocol2 {} // expected-warning {{extension declares a conformance of imported type 'Sample6b' to imported protocol 'SampleProtocol2'; this will not behave correctly if the owners of 'Library' introduce this conformance in the future}}
96+
// expected-note @-1 {{add '@retroactive' to silence this warning}}
97+
extension Sample6c: Library.SampleProtocol1a {} // ok, protocol is module qualified.
8998

9099
protocol ClientProtocol {}
91100

@@ -125,10 +134,20 @@ extension Sample7: SampleProtocol1 & SampleProtocol2 {}
125134

126135
extension Sample8: @retroactive SampleProtocol1 & SampleProtocol2 {} // ok
127136

137+
// FIXME: Module qualification should suppress this warning
138+
extension Sample8a: Library.SampleProtocol1 & Library.SampleProtocol2 {} // ok
139+
// expected-warning@-1 {{extension declares a conformance of imported type 'Sample8a' to imported protocols 'SampleProtocol1', 'SampleProtocol2'; this will not behave correctly if the owners of 'Library' introduce this conformance in the future}}
140+
// expected-note@-2 {{add '@retroactive' to silence this warning}}
141+
128142
extension Sample9: SampleProtocol3<Int> {}
129143
// expected-warning@-1 {{extension declares a conformance of imported type 'Sample9' to imported protocol 'SampleProtocol3'; this will not behave correctly if the owners of 'Library' introduce this conformance in the future}}
130144
// expected-note@-2 {{add '@retroactive' to silence this warning}}
131145

132-
extension Sample10: @retroactive SampleProtocol3<Int> {}
146+
extension Sample9a: @retroactive SampleProtocol3<Int> {}
133147

134-
#endif
148+
// FIXME: Module qualification should suppress this warning
149+
extension Sample9b: Library.SampleProtocol3<Int> {}
150+
// expected-warning@-1 {{extension declares a conformance of imported type 'Sample9b' to imported protocol 'SampleProtocol3'; this will not behave correctly if the owners of 'Library' introduce this conformance in the future}}
151+
// expected-note@-2 {{add '@retroactive' to silence this warning}}
152+
153+
#endif

0 commit comments

Comments
 (0)