Skip to content

Commit f227643

Browse files
committed
[test] Add some constructor ranking test cases
1 parent 94f4aca commit f227643

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed

test/Constraints/ranking.swift

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,80 @@ extension X where Self : GenericClass<String> {
269269
}
270270
}
271271

272+
//--------------------------------------------------------------------
273+
// Constructor-specific ranking
274+
//--------------------------------------------------------------------
275+
276+
// We have a special ranking rule that only currently applies to constructors,
277+
// and compares the concrete parameter types.
278+
279+
protocol Q {
280+
init()
281+
}
282+
283+
struct S1<T : Q> {
284+
// We want to prefer the non-optional init over the optional init here.
285+
init(_ x: T = .init()) {}
286+
init(_ x: T? = nil) {}
287+
288+
// CHECK-LABEL: sil hidden [ossa] @$s7ranking2S1V11testRankingACyxGyt_tcfC
289+
init(testRanking: Void) {
290+
// CHECK: function_ref @$s7ranking2S1VyACyxGxcfC : $@convention(method) <τ_0_0 where τ_0_0 : Q> (@in τ_0_0, @thin S1<τ_0_0>.Type) -> S1<τ_0_0>
291+
self.init()
292+
}
293+
294+
// CHECK-LABEL: sil hidden [ossa] @$s7ranking2S1V15testInitRankingyyF
295+
func testInitRanking() {
296+
// CHECK: function_ref @$s7ranking2S1VyACyxGxcfC : $@convention(method) <τ_0_0 where τ_0_0 : Q> (@in τ_0_0, @thin S1<τ_0_0>.Type) -> S1<τ_0_0>
297+
_ = S1<T>()
298+
}
299+
}
300+
301+
protocol R {}
302+
extension Array : R {}
303+
extension Int : R {}
304+
305+
struct S2 {
306+
init(_ x: R) {}
307+
init(_ x: Int...) {}
308+
309+
// CHECK-LABEL: sil hidden [ossa] @$s7ranking2S2V15testInitRankingyyF
310+
func testInitRanking() {
311+
// We currently prefer the non-variadic init due to having
312+
// "less effective parameters", and we don't compare the types for ranking due
313+
// to the difference in variadic-ness.
314+
// CHECK: function_ref @$s7ranking2S2VyAcA1R_pcfC : $@convention(method) (@in R, @thin S2.Type) -> S2
315+
_ = S2(0)
316+
}
317+
}
318+
319+
// Very cursed: As a holdover from how we used to represent function inputs,
320+
// we rank these as tuples and consider (x:x:) to be a subtype of (x:y:). Seems
321+
// unlikely this is being relied on in the real world, but let's at least have
322+
// it as a test case to track its behavior.
323+
struct S3 {
324+
init(x _: Int = 0, y _: Int = 0) {}
325+
init(x _: Int = 0, x _: Int = 0) {}
326+
327+
func testInitRanking() {
328+
// CHECK: function_ref @$s7ranking2S3V1xAdCSi_SitcfC : $@convention(method) (Int, Int, @thin S3.Type) -> S3
329+
_ = S3()
330+
}
331+
}
332+
333+
// Also another consequence of having ranked as tuples: we prefer the unlabeled
334+
// init here.
335+
struct S4 {
336+
init(x: Int = 0, y: Int = 0) {}
337+
init(_ x: Int = 0, _ y: Int = 0) {}
338+
339+
// CHECK-LABEL: sil hidden [ossa] @$s7ranking2S4V15testInitRankingyyF
340+
func testInitRanking() {
341+
// CHECK: function_ref @$s7ranking2S4VyACSi_SitcfC : $@convention(method) (Int, Int, @thin S4.Type) -> S4
342+
_ = S4()
343+
}
344+
}
345+
272346
//--------------------------------------------------------------------
273347
// Pointer conversions
274348
//--------------------------------------------------------------------
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// We have a special ranking rule that only currently applies to constructors,
4+
// and compares the concrete parameter types.
5+
6+
protocol P {
7+
init()
8+
}
9+
10+
// We currently only apply the constructor ranking rule to X() and not X.init().
11+
struct S<T : P> {
12+
init(_ x: T = .init()) {} // expected-note {{found this candidate}}
13+
init(_ x: T? = nil) {} // expected-note {{found this candidate}}
14+
func testInitRanking() {
15+
_ = S<T>() // Okay
16+
_ = S<T>.init() // expected-error {{ambiguous use of 'init(_:)'}}
17+
}
18+
}
19+
struct S1 {
20+
init(x: Int = 0, y: Int = 0) {} // expected-note {{found this candidate}}
21+
init(_ x: Int = 0, _ y: Int = 0) {} // expected-note {{found this candidate}}
22+
23+
func testInitRanking() {
24+
_ = S1() // Okay
25+
_ = S1.init() // expected-error {{ambiguous use of 'init'}}
26+
}
27+
}

0 commit comments

Comments
 (0)