Skip to content

Commit 10dc220

Browse files
authored
Merge pull request #15751 from huonw/cond-conf-fixits
Fix & improve the fixits for conditional conformances.
2 parents c570215 + ae1b06b commit 10dc220

File tree

5 files changed

+33
-17
lines changed

5 files changed

+33
-17
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,6 +1453,9 @@ NOTE(note_explicitly_state_conditional_conformance_relaxed,none,
14531453
"did you mean to explicitly state the conformance with relaxed bounds?", ())
14541454
NOTE(note_explicitly_state_conditional_conformance_same,none,
14551455
"did you mean to explicitly state the conformance with the same bounds?", ())
1456+
NOTE(note_explicitly_state_conditional_conformance_noneditor,none,
1457+
"did you mean to explicitly state the conformance like '%0where ...'?",
1458+
(StringRef))
14561459
ERROR(protocol_has_missing_requirements,none,
14571460
"type %0 cannot conform to protocol %1 because it has requirements that "
14581461
"cannot be satisfied", (Type, Type))

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,8 +1300,9 @@ static void diagnoseConformanceImpliedByConditionalConformance(
13001300
// want to encourage it.
13011301

13021302
auto ext = cast<ExtensionDecl>(implyingConf->getDeclContext());
1303+
auto &ctxt = ext->getASTContext();
13031304

1304-
auto &SM = ext->getASTContext().SourceMgr;
1305+
auto &SM = ctxt.SourceMgr;
13051306
StringRef extraIndent;
13061307
StringRef indent = Lexer::getIndentationForLine(SM, loc, &extraIndent);
13071308

@@ -1313,13 +1314,27 @@ static void diagnoseConformanceImpliedByConditionalConformance(
13131314
llvm::raw_svector_ostream prefixStream(prefix);
13141315
llvm::raw_svector_ostream suffixStream(suffix);
13151316

1316-
prefixStream << "extension " << T << ": " << protoType << " ";
1317+
ValueDecl *decl = T->getAnyNominal();
1318+
if (!decl)
1319+
decl = T->getAnyGeneric();
1320+
1321+
prefixStream << "extension " << decl->getFullName() << ": " << protoType << " ";
13171322
suffixStream << " {\n"
13181323
<< indent << extraIndent << "<#witnesses#>\n"
13191324
<< indent << "}\n\n"
13201325
<< indent;
13211326
}
13221327

1328+
if (!ctxt.LangOpts.DiagnosticsEditorMode) {
1329+
// The fixits below are too complicated for the command line: the suggested
1330+
// code ends up not being displayed, and the text by itself doesn't help. So
1331+
// instead we skip all that and just have some text.
1332+
Diags.diagnose(loc,
1333+
diag::note_explicitly_state_conditional_conformance_noneditor,
1334+
prefix.str());
1335+
return;
1336+
}
1337+
13231338
// First, we do the fixit for "matching" requirements (i.e. X: P where T: P).
13241339
bool matchingIsValid = true;
13251340
llvm::SmallString<128> matchingFixit = prefix;

test/Generics/conditional_conformances.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,16 +279,14 @@ struct InheritImplicitOne<T> {}
279279
// incorrect/insufficiently general).
280280
extension InheritImplicitOne: P5 where T: P1 {}
281281
// expected-error@-1{{conditional conformance of type 'InheritImplicitOne<T>' to protocol 'P5' does not imply conformance to inherited protocol 'P2'}}
282-
// expected-note@-2{{did you mean to explicitly state the conformance with the same bounds?}}
283-
// expected-note@-3{{did you mean to explicitly state the conformance with different bounds?}}
282+
// expected-note@-2{{did you mean to explicitly state the conformance like 'extension InheritImplicitOne: P2 where ...'?}}
284283

285284
struct InheritImplicitTwo<T> {}
286285
// Even if we relax the rule about implication, this double-up should still be
287286
// an error, because either conformance could imply InheritImplicitTwo: P2.
288287
extension InheritImplicitTwo: P5 where T: P1 {}
289288
// expected-error@-1{{conditional conformance of type 'InheritImplicitTwo<T>' to protocol 'P5' does not imply conformance to inherited protocol 'P2'}}
290-
// expected-note@-2{{did you mean to explicitly state the conformance with the same bounds?}}
291-
// expected-note@-3{{did you mean to explicitly state the conformance with different bounds?}}
289+
// expected-note@-2{{did you mean to explicitly state the conformance like 'extension InheritImplicitTwo: P2 where ...'?}}
292290
extension InheritImplicitTwo: P6 where T: P1 {}
293291

294292
// However, if there's a non-conditional conformance that implies something, we

test/Generics/conditional_conformances_fixit.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -emit-fixits-path %t.remap -fixit-all
1+
// RUN: %target-typecheck-verify-swift -emit-fixits-path %t.remap -fixit-all -diagnostics-editor-mode
22
// RUN: c-arcmt-test %t.remap | arcmt-test -verify-transformed-files %s.result
33

44
protocol P1 {}

test/Generics/conditional_conformances_fixit.swift.result

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -emit-fixits-path %t.remap -fixit-all
1+
// RUN: %target-typecheck-verify-swift -emit-fixits-path %t.remap -fixit-all -diagnostics-editor-mode
22
// RUN: c-arcmt-test %t.remap | arcmt-test -verify-transformed-files %s.result
33

44
protocol P1 {}
@@ -7,11 +7,11 @@ protocol P2: P1 {}
77

88
struct S1<T> {}
99

10-
extension S1<T>: P1 where T: P1 {
10+
extension S1: P1 where T: P1 {
1111
<#witnesses#>
1212
}
1313

14-
extension S1<T>: P1 where <#requirements#> {
14+
extension S1: P1 where <#requirements#> {
1515
<#witnesses#>
1616
}
1717

@@ -25,15 +25,15 @@ protocol P3 {
2525
}
2626
struct S2<T, U, V: P3> {}
2727

28-
extension S2<T, U, V>: P1 where T: P1, U: P1, V.X: P1 {
28+
extension S2: P1 where T: P1, U: P1, V.X: P1 {
2929
<#witnesses#>
3030
}
3131

32-
extension S2<T, U, V>: P1 where T: P2, U: P2, V.X: P2 {
32+
extension S2: P1 where T: P2, U: P2, V.X: P2 {
3333
<#witnesses#>
3434
}
3535

36-
extension S2<T, U, V>: P1 where <#requirements#> {
36+
extension S2: P1 where <#requirements#> {
3737
<#witnesses#>
3838
}
3939

@@ -46,11 +46,11 @@ extension S2: P2 where T: P2, U: P2, V.X: P2 {}
4646

4747
struct S3<T, U, V: P3> {}
4848

49-
extension S3<T, U, V>: P1 where T: P2, U: P2, V.X == Int {
49+
extension S3: P1 where T: P2, U: P2, V.X == Int {
5050
<#witnesses#>
5151
}
5252

53-
extension S3<T, U, V>: P1 where <#requirements#> {
53+
extension S3: P1 where <#requirements#> {
5454
<#witnesses#>
5555
}
5656

@@ -62,11 +62,11 @@ extension S3: P2 where T: P2, U: P2, V.X == Int {}
6262

6363
struct S4<T, U, V: P3> {}
6464

65-
extension S4<T, U, V>: P1 where T: P2, U: P3, V.X: P2 {
65+
extension S4: P1 where T: P2, U: P3, V.X: P2 {
6666
<#witnesses#>
6767
}
6868

69-
extension S4<T, U, V>: P1 where <#requirements#> {
69+
extension S4: P1 where <#requirements#> {
7070
<#witnesses#>
7171
}
7272

0 commit comments

Comments
 (0)