Skip to content

Commit 5b6f183

Browse files
authored
Merge pull request swiftlang#38904 from al45tair/problem/37170485
[Tests] Re-add round-trip type test.
2 parents 3637c13 + 642b93d commit 5b6f183

19 files changed

+736
-4
lines changed

docs/Testing.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,16 @@ code for the target that is not the build machine:
384384

385385
Add ``REQUIRES: static_stdlib`` to the test.
386386

387+
* ``%target-rtti-opt``: the ``-frtti`` or ``-fno-rtti`` option required to
388+
link with the Swift libraries on the target platform.
389+
390+
* ``%target-cxx-lib``: the argument to add to the command line when using
391+
``swiftc`` and linking in a C++ object file. Typically ``-lc++`` or
392+
``-lstdc++`` depending on platform.
393+
394+
* ``%target-msvc-runtime-opt``: for Windows, the MSVC runtime option, e.g.
395+
``-MD``, to use when building C/C++ code to link with Swift.
396+
387397
Always use ``%target-*`` substitutions unless you have a good reason. For
388398
example, an exception would be a test that checks how the compiler handles
389399
mixing module files for incompatible platforms (that test would need to compile

stdlib/public/runtime/Private.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,9 @@ class TypeInfo {
268268
const ContextDescriptor *
269269
_searchConformancesByMangledTypeName(Demangle::NodePointer node);
270270

271+
SWIFT_RUNTIME_EXPORT
271272
Demangle::NodePointer _swift_buildDemanglingForMetadata(const Metadata *type,
272-
Demangle::Demangler &Dem);
273+
Demangle::Demangler &Dem);
273274

274275
/// Callback used to provide the substitution of a generic parameter
275276
/// (described by depth/index) to its metadata.
@@ -367,13 +368,15 @@ class TypeInfo {
367368
unsigned index) const;
368369
};
369370

371+
#pragma clang diagnostic push
372+
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
370373
/// Retrieve the type metadata described by the given demangled type name.
371374
///
372375
/// \p substGenericParam Function that provides generic argument metadata
373376
/// given a particular generic parameter specified by depth/index.
374377
/// \p substWitnessTable Function that provides witness tables given a
375378
/// particular dependent conformance index.
376-
SWIFT_CC(swift)
379+
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
377380
TypeLookupErrorOr<TypeInfo> swift_getTypeByMangledNode(
378381
MetadataRequest request,
379382
Demangler &demangler,
@@ -388,13 +391,14 @@ class TypeInfo {
388391
/// given a particular generic parameter specified by depth/index.
389392
/// \p substWitnessTable Function that provides witness tables given a
390393
/// particular dependent conformance index.
391-
SWIFT_CC(swift)
394+
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
392395
TypeLookupErrorOr<TypeInfo> swift_getTypeByMangledName(
393396
MetadataRequest request,
394397
StringRef typeName,
395398
const void * const *arguments,
396399
SubstGenericParameterFn substGenericParam,
397400
SubstDependentWitnessTableFn substWitnessTable);
401+
#pragma clang diagnostic pop
398402

399403
/// Function object that produces substitutions for the generic parameters
400404
/// that occur within a mangled name, using the complete set of generic
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include "swift/ABI/Metadata.h"
2+
#include "swift/Demangling/Demangle.h"
3+
#include "swift/Reflection/TypeRefBuilder.h"
4+
#include "swift/Remote/MetadataReader.h"
5+
#include "swift/Remote/InProcessMemoryReader.h"
6+
7+
#include "Private.h"
8+
9+
#include <cstdio>
10+
11+
using namespace swift;
12+
13+
static std::string nameForMetadata(const Metadata *md)
14+
{
15+
Demangle::__runtime::StackAllocatedDemangler<1024> dem;
16+
auto nodeTree = _swift_buildDemanglingForMetadata(md, dem);
17+
if (!nodeTree)
18+
return "<unknown>";
19+
20+
std::string result = Demangle::__runtime::nodeToString(nodeTree);
21+
return result;
22+
}
23+
24+
extern "C" SWIFT_CC(swift) void roundTripType(const Metadata *md) {
25+
// Get a name for it
26+
const std::string mdName = ::nameForMetadata(md);
27+
28+
// Convert it to a Node tree
29+
Demangle::__runtime::StackAllocatedDemangler<1024> dem;
30+
auto nodeTree = _swift_buildDemanglingForMetadata(md, dem);
31+
32+
// Mangle that
33+
std::string mangledName = Demangle::__runtime::mangleNode(nodeTree);
34+
35+
// Look up the result
36+
auto result = swift_getTypeByMangledName(MetadataState::Abstract,
37+
mangledName,
38+
nullptr,
39+
[](unsigned, unsigned){ return nullptr; },
40+
[](const Metadata *, unsigned) { return nullptr; });
41+
if (result.isError()) {
42+
auto err = result.getError();
43+
char *errStr = err->copyErrorString();
44+
printf("FAIL: %s (%p) -> %s -> ERROR %s\n",
45+
mdName.c_str(), md, mangledName.c_str(), errStr);
46+
err->freeErrorString(errStr);
47+
nodeTree->dump();
48+
49+
result = swift_getTypeByMangledNode(MetadataState::Abstract,
50+
dem,
51+
nodeTree,
52+
nullptr,
53+
[](unsigned, unsigned){ return nullptr; },
54+
[](const Metadata *, unsigned) { return nullptr; });
55+
if (result.isError()) {
56+
err = result.getError();
57+
char *errStr = err->copyErrorString();
58+
printf("=> Also failed on node: %s\n", errStr);
59+
err->freeErrorString(errStr);
60+
}
61+
return;
62+
}
63+
64+
const Metadata *md2 = result.getType().getMetadata();
65+
66+
std::string md2Name = "<FAIL>";
67+
68+
if (md2)
69+
md2Name = ::nameForMetadata(md2);
70+
71+
printf("%s: %s (%p) -> %s -> %s (%p)\n",
72+
md == md2 ? "PASS" : "FAIL",
73+
mdName.c_str(), md, mangledName.c_str(), md2Name.c_str(), md2);
74+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@_silgen_name("roundTripType")
2+
public func roundTripType(_: Any.Type)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import RoundTrip
2+
3+
public func test() {
4+
roundTripType(Int.self)
5+
roundTripType(UInt.self)
6+
7+
roundTripType(Float.self)
8+
roundTripType(Double.self)
9+
10+
roundTripType(Int8.self)
11+
roundTripType(Int16.self)
12+
roundTripType(Int32.self)
13+
roundTripType(Int64.self)
14+
15+
roundTripType(UInt8.self)
16+
roundTripType(UInt16.self)
17+
roundTripType(UInt32.self)
18+
roundTripType(UInt64.self)
19+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import RoundTrip
2+
3+
public func test() {
4+
roundTripType(Array<(Int) async -> ()>.self)
5+
roundTripType(Array<(Int) async throws -> ()>.self)
6+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import RoundTrip
2+
3+
protocol P {}
4+
protocol Q {}
5+
class C {}
6+
class D : C, P, Q {}
7+
8+
public func test() {
9+
roundTripType(Any.self)
10+
roundTripType(AnyObject.self)
11+
roundTripType(P.self)
12+
roundTripType((C & P).self)
13+
roundTripType((P & AnyObject).self)
14+
roundTripType((P & Q).self)
15+
roundTripType((C & P & Q).self)
16+
roundTripType((P & Q & AnyObject).self)
17+
18+
roundTripType(Any.Type.self)
19+
roundTripType(AnyObject.Type.self)
20+
roundTripType(P.Type.self)
21+
roundTripType((C & P).Type.self)
22+
roundTripType((P & AnyObject).Type.self)
23+
roundTripType((P & Q).Type.self)
24+
roundTripType((C & P & Q).Type.self)
25+
roundTripType((P & Q & AnyObject).Type.self)
26+
27+
roundTripType(Any.Protocol.self)
28+
roundTripType(AnyObject.Protocol.self)
29+
roundTripType(P.Protocol.self)
30+
roundTripType((C & P).Protocol.self)
31+
roundTripType((P & AnyObject).Protocol.self)
32+
roundTripType((P & Q).Protocol.self)
33+
roundTripType((C & P & Q).Protocol.self)
34+
roundTripType((P & Q & AnyObject).Protocol.self)
35+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import RoundTrip
2+
3+
struct Concrete {}
4+
5+
extension Concrete {
6+
struct Nested {}
7+
}
8+
9+
struct Generic<T> {}
10+
11+
protocol Proto {}
12+
13+
struct Foo : Proto {}
14+
15+
class Bar {}
16+
17+
extension Generic where T : Proto {
18+
struct Nested1 {}
19+
}
20+
21+
extension Generic where T == Int {
22+
struct Nested2 {}
23+
}
24+
25+
extension Generic where T: AnyObject {
26+
struct NestedViaAnyObject {}
27+
}
28+
29+
public func test() {
30+
roundTripType(Concrete.Nested.self)
31+
roundTripType(Generic<Foo>.Nested1.self)
32+
roundTripType(Generic<Int>.Nested2.self)
33+
roundTripType(Generic<Bar>.NestedViaAnyObject.self)
34+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import RoundTrip
2+
3+
class Class {}
4+
5+
let fn: (Int, Class, __owned Class, Any, inout Int) -> (Int, Class, Any) = {
6+
_, _, _, _, _ in fatalError()
7+
}
8+
9+
let fn2: () throws -> () = {}
10+
11+
public func test() {
12+
roundTripType(type(of: fn))
13+
roundTripType(type(of: fn2))
14+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import RoundTrip
2+
3+
protocol First {
4+
associatedtype Assoc : First
5+
6+
// Just to confuse things -- a method with the same name as an
7+
// associated type
8+
func Assoc(_: Int) -> Int
9+
}
10+
11+
protocol Second {
12+
associatedtype Assoc : Second
13+
}
14+
15+
struct OuterFirst<A : First, B : First> {
16+
struct Inner<C : First, D : First> {
17+
func method(a: A, b: B, c: C, d: D) {
18+
do {
19+
let _: (A, A.Assoc, A.Assoc.Assoc) -> () = { _, _, _ in }
20+
}
21+
do {
22+
let _: (B, B.Assoc, B.Assoc.Assoc) -> () = { _, _, _ in }
23+
}
24+
do {
25+
let _: (C, C.Assoc, C.Assoc.Assoc) -> () = { _, _, _ in }
26+
}
27+
do {
28+
let _: (D, D.Assoc, D.Assoc.Assoc) -> () = { _, _, _ in }
29+
}
30+
}
31+
}
32+
}
33+
34+
struct OuterBoth<A : First & Second, B : First & Second> {
35+
struct Inner<C : First & Second, D : First & Second> {
36+
func method(a: A, b: B, c: C, d: D) {
37+
do {
38+
let _: (A, A.Assoc, A.Assoc.Assoc) -> () = { _, _, _ in }
39+
}
40+
do {
41+
let _: (B, B.Assoc, B.Assoc.Assoc) -> () = { _, _, _ in }
42+
}
43+
do {
44+
let _: (C, C.Assoc, C.Assoc.Assoc) -> () = { _, _, _ in }
45+
}
46+
do {
47+
let _: (D, D.Assoc, D.Assoc.Assoc) -> () = { _, _, _ in }
48+
}
49+
}
50+
}
51+
}
52+
53+
struct F1: First {
54+
typealias Assoc = F2
55+
56+
func Assoc(_ x: Int) -> Int { return x + 1 }
57+
}
58+
59+
struct F2: First {
60+
typealias Assoc = F1
61+
62+
func Assoc(_ x: Int) -> Int { return x * 2 }
63+
}
64+
65+
struct FS1: First, Second {
66+
typealias Assoc = FS2
67+
68+
func Assoc(_ x: Int) -> Int { return x - 1 }
69+
}
70+
71+
struct FS2: First, Second {
72+
typealias Assoc = FS1
73+
74+
func Assoc(_ x: Int) -> Int { return x / 2 }
75+
}
76+
77+
public func test() {
78+
roundTripType(OuterFirst<F1,F2>.self)
79+
roundTripType(OuterBoth<FS1,FS2>.self)
80+
roundTripType(OuterFirst<F1,F2>.Inner<F2,F1>.self)
81+
roundTripType(OuterBoth<FS1,FS2>.Inner<FS2,FS1>.self)
82+
roundTripType(type(of:OuterFirst<F1,F2>.Inner<F2,F1>.method))
83+
roundTripType(type(of:OuterBoth<FS1,FS2>.Inner<FS2,FS1>.method))
84+
}

0 commit comments

Comments
 (0)