Skip to content

Commit e26109f

Browse files
authored
Merge pull request #64459 from hyp/eng/conforms_to++
[interop] 'conforms_to' attribute should be qualified with module name
2 parents 5052daa + 90d1c24 commit e26109f

File tree

7 files changed

+71
-27
lines changed

7 files changed

+71
-27
lines changed

include/swift/AST/DiagnosticsClangImporter.def

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -233,15 +233,20 @@ ERROR(foreign_reference_types_invalid_release,none,
233233
"specified release function '%0' is invalid. Release must have exactly "
234234
"one argument of type '%1'", (StringRef, StringRef))
235235

236+
237+
ERROR(conforms_to_missing_dot,none,
238+
"expected module name and protocol name separated by '.' in protocol conformance; '%0' is invalid", (StringRef))
239+
ERROR(cannot_find_conforms_to_module,none,
240+
"module '%1' in specified protocol conformance '%0' is not found; did you mean to import it first?", (StringRef, StringRef))
241+
236242
ERROR(cannot_find_conforms_to,none,
237-
"specified protocol conformance could not be found '%0'.", (StringRef))
243+
"protocol '%0' in specified protocol conformance is not found in module '%1'", (StringRef, StringRef))
238244

239245
ERROR(conforms_to_ambiguous,none,
240-
"specified protocol conformance is ambiguous. "
241-
"Found multiple protocols named '%0'.", (StringRef))
246+
"ambiguous reference to protocol '%0' in specified protocol conformance; module '%1' contains multiple protocols named '%0'", (StringRef, StringRef))
242247

243248
ERROR(conforms_to_not_protocol,none,
244-
"specified protocol conformance '%0' is not a protocol.", (StringRef))
249+
"%0 %1 referenced in protocol conformance '%2' is not a protocol", (DescriptiveDeclKind, ValueDecl *, StringRef))
245250

246251
NOTE(unsupported_builtin_type, none, "built-in type '%0' not supported", (StringRef))
247252
NOTE(record_field_not_imported, none, "field %0 unavailable (cannot import)", (const clang::NamedDecl*))

lib/ClangImporter/ImportDecl.cpp

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2658,23 +2658,38 @@ namespace {
26582658
if (conformsToAttr == clangDecl->getAttrs().end())
26592659
return;
26602660

2661-
auto name = cast<clang::SwiftAttrAttr>(*conformsToAttr)
2662-
->getAttribute()
2663-
.drop_front(StringRef("conforms_to:").size())
2664-
.str();
2665-
2666-
for (auto &module : Impl.SwiftContext.getLoadedModules()) {
2667-
module.second->lookupValue(Impl.SwiftContext.getIdentifier(name),
2668-
NLKind::UnqualifiedLookup, results);
2661+
auto conformsToValue = cast<clang::SwiftAttrAttr>(*conformsToAttr)
2662+
->getAttribute()
2663+
.drop_front(StringRef("conforms_to:").size())
2664+
.str();
2665+
auto names = StringRef(conformsToValue).split('.');
2666+
auto moduleName = names.first;
2667+
auto protocolName = names.second;
2668+
if (protocolName.empty()) {
2669+
HeaderLoc attrLoc((*conformsToAttr)->getLocation());
2670+
Impl.diagnose(attrLoc, diag::conforms_to_missing_dot, conformsToValue);
2671+
return;
26692672
}
26702673

2674+
auto *mod = Impl.SwiftContext.getModuleByIdentifier(
2675+
Impl.SwiftContext.getIdentifier(moduleName));
2676+
if (!mod) {
2677+
HeaderLoc attrLoc((*conformsToAttr)->getLocation());
2678+
Impl.diagnose(attrLoc, diag::cannot_find_conforms_to_module,
2679+
conformsToValue, moduleName);
2680+
return;
2681+
}
2682+
mod->lookupValue(Impl.SwiftContext.getIdentifier(protocolName),
2683+
NLKind::UnqualifiedLookup, results);
26712684
if (results.empty()) {
26722685
HeaderLoc attrLoc((*conformsToAttr)->getLocation());
2673-
Impl.diagnose(attrLoc, diag::cannot_find_conforms_to, name);
2686+
Impl.diagnose(attrLoc, diag::cannot_find_conforms_to, protocolName,
2687+
moduleName);
26742688
return;
26752689
} else if (results.size() != 1) {
26762690
HeaderLoc attrLoc((*conformsToAttr)->getLocation());
2677-
Impl.diagnose(attrLoc, diag::conforms_to_ambiguous, name);
2691+
Impl.diagnose(attrLoc, diag::conforms_to_ambiguous, protocolName,
2692+
moduleName);
26782693
return;
26792694
}
26802695

@@ -2684,7 +2699,8 @@ namespace {
26842699
new (Impl.SwiftContext) SynthesizedProtocolAttr(protocol, &Impl, false));
26852700
} else {
26862701
HeaderLoc attrLoc((*conformsToAttr)->getLocation());
2687-
Impl.diagnose(attrLoc, diag::conforms_to_not_protocol, name);
2702+
Impl.diagnose(attrLoc, diag::conforms_to_not_protocol,
2703+
result->getDescriptiveKind(), result, conformsToValue);
26882704
}
26892705
}
26902706

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
14
1+
15
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public protocol ProtocolFromImportedModule {
2+
func testImported()
3+
}

test/Interop/Cxx/class/Inputs/conforms-to.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,24 @@
22
#define TEST_INTEROP_CXX_CLASS_INPUTS_DESTRUCTORS_H
33

44
struct
5-
__attribute__((swift_attr("conforms_to:Testable")))
5+
__attribute__((swift_attr("conforms_to:SwiftTest.Testable")))
66
HasTest {
77
void test() const;
88
};
99

1010
struct
11-
__attribute__((swift_attr("conforms_to:Playable")))
11+
__attribute__((swift_attr("conforms_to:SwiftTest.Playable")))
1212
__attribute__((swift_attr("import_reference")))
1313
__attribute__((swift_attr("retain:immortal")))
1414
__attribute__((swift_attr("release:immortal")))
1515
HasPlay {
1616
void play() const;
1717
};
1818

19+
struct
20+
__attribute__((swift_attr("conforms_to:ImportedModule.ProtocolFromImportedModule")))
21+
HasImportedConf {
22+
void testImported() const;
23+
};
1924

2025
#endif // TEST_INTEROP_CXX_CLASS_INPUTS_DESTRUCTORS_H
Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: rm -rf %t
22
// RUN: split-file %s %t
3-
// RUN: not %target-swift-frontend -typecheck -I %t/Inputs %t/test.swift -enable-experimental-cxx-interop 2>&1 | %FileCheck %s
3+
// RUN: not %target-swift-frontend -typecheck -I %t/Inputs %t/test.swift -enable-experimental-cxx-interop -module-name SwiftTest 2>&1 | %FileCheck %s
44

55
//--- Inputs/module.modulemap
66
module Test {
@@ -10,9 +10,11 @@ module Test {
1010

1111
//--- Inputs/test.h
1212

13-
struct __attribute__((swift_attr("conforms_to:X"))) CX {};
14-
struct __attribute__((swift_attr("conforms_to:A"))) CA {};
15-
struct __attribute__((swift_attr("conforms_to:B"))) CB {};
13+
struct __attribute__((swift_attr("conforms_to:X"))) CInv {};
14+
struct __attribute__((swift_attr("conforms_to:Mod.X"))) CModInv {};
15+
struct __attribute__((swift_attr("conforms_to:SwiftTest.X"))) CX {};
16+
struct __attribute__((swift_attr("conforms_to:SwiftTest.A"))) CA {};
17+
struct __attribute__((swift_attr("conforms_to:SwiftTest.B"))) CB {};
1618

1719
//--- test.swift
1820

@@ -23,8 +25,10 @@ struct B {}
2325
protocol A {}
2426
protocol A {}
2527

26-
// CHECK: error: specified protocol conformance could not be found 'X'.
27-
// CHECK: error: specified protocol conformance is ambiguous. Found multiple protocols named 'A'.
28-
// CHECK: error: specified protocol conformance 'B' is not a protocol.
28+
// CHECK: error: expected module name and protocol name separated by '.' in protocol conformance; 'X' is invalid
29+
// CHECK: module 'Mod' in specified protocol conformance 'Mod.X' is not found; did you mean to import it first?
30+
// CHECK: error: protocol 'X' in specified protocol conformance is not found in module 'SwiftTest'
31+
// CHECK: error: ambiguous reference to protocol 'A' in specified protocol conformance; module 'SwiftTest' contains multiple protocols named 'A'
32+
// CHECK: error: struct 'B' referenced in protocol conformance 'SwiftTest.B' is not a protocol
2933

30-
func test(_ x: CX, _ a: CA, _ b: CB) {}
34+
func test(_ inv: CInv, _ invMod: CModInv, _ x: CX, _ a: CA, _ b: CB) {}

test/Interop/Cxx/class/conforms-to.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -enable-experimental-cxx-interop
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %S/Inputs/conforms-to-imported.swift -module-name ImportedModule -emit-module -emit-module-path %t/ImportedModule.swiftmodule
3+
4+
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %t -I %S/Inputs -module-name SwiftTest -enable-experimental-cxx-interop
25

36
import ConformsTo
7+
import ImportedModule
48

59
protocol Testable {
610
func test()
@@ -25,3 +29,10 @@ func callee(_ _: Playable) {
2529
func caller(_ x: Playable) {
2630
callee(x)
2731
}
32+
33+
func callee(_ _: ProtocolFromImportedModule) {
34+
}
35+
36+
func caller(_ x: HasImportedConf) {
37+
callee(x)
38+
}

0 commit comments

Comments
 (0)