Skip to content

Commit 0bae11b

Browse files
committed
[CSRanking] Fix func declaration ranking with default'ed parameters
If default'ed parameters in one decl are intermixed with non-defaulted ones, skip claiming parameters in other decl at the same position. Resolves: rdar://problem/36226874.
1 parent a0b5e63 commit 0bae11b

File tree

3 files changed

+90
-67
lines changed

3 files changed

+90
-67
lines changed

lib/Sema/CSRanking.cpp

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -635,23 +635,43 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
635635
return true;
636636
};
637637

638-
for (unsigned i = 0; i != numParams2; ++i) {
639-
// If there is no corresponding argument in the first
640-
// parameter list...
641-
if (i >= numParams1) {
642-
// We need either a default argument or a variadic
643-
// argument for the first declaration to be more
644-
// specialized.
645-
if (!defaultMapType2[i] &&
646-
!params2[i].isVariadic())
638+
for (unsigned param1 = 0, param2 = 0; param2 != numParams2; ++param2) {
639+
// If there is a default for parameter in the second function
640+
// while there are still some parameters left unclaimed in first,
641+
// it could only mean that default parameters are intermixed e.g.
642+
//
643+
// ```swift
644+
// func foo(a: Int) {}
645+
// func foo(q: String = "", a: Int) {}
646+
// ```
647+
// or
648+
// ```swift
649+
// func foo(a: Int, c: Int) {}
650+
// func foo(a: Int, b: Int = 0, c: Int) {}
651+
// ```
652+
// and we shouldn't claim parameter from the first function.
653+
if (param1 < numParams1 && numParams1 != numParams2 &&
654+
defaultMapType2[param2]) {
655+
fewerEffectiveParameters = true;
656+
continue;
657+
}
658+
659+
// If we've claimed all of the parameters from first
660+
// function, the rest of the parameters in second should
661+
// be either default or variadic.
662+
if (param1 >= numParams1) {
663+
if (!defaultMapType2[param2] && !params2[param2].isVariadic())
647664
return false;
648665

649666
fewerEffectiveParameters = true;
650667
continue;
651668
}
652669

653-
if (!maybeAddSubtypeConstraint(params1[i], params2[i]))
670+
if (!maybeAddSubtypeConstraint(params1[param1], params2[param2]))
654671
return false;
672+
673+
// claim the parameter as used.
674+
++param1;
655675
}
656676

657677
if (compareTrailingClosureParamsSeparately)

test/Compatibility/trailing-closure.swift

Lines changed: 47 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -274,78 +274,68 @@ func testOverloadAmbiguity() {
274274
overloadOnSomeDefaultArgsOnly3(1) {} // expected-error {{ambiguous use of 'overloadOnSomeDefaultArgsOnly3(_:x:a:)'}}
275275
}
276276

277-
func overloadMismatch(a: () -> Void) -> Bool { return true} // expected-note 2 {{found this candidate}}
278-
func overloadMismatch(x: Int = 0, a: () -> Void) -> Int { return 0 } // expected-note 2 {{found this candidate}}
277+
func overloadMismatch(a: () -> Void) -> Bool { return true}
278+
func overloadMismatch(x: Int = 0, a: () -> Void) -> Int { return 0 }
279279

280280
func overloadMismatchLabel(a: () -> Void) -> Bool { return true}
281281
func overloadMismatchLabel(x: Int = 0, b: () -> Void) -> Int { return 0 }
282282

283-
func overloadMismatchArgs(_: Int, a: () -> Void) -> Bool { return true} // expected-note {{found this candidate}}
284-
func overloadMismatchArgs(_: Int, x: Int = 0, a: () -> Void) -> Int { return 0 } // expected-note {{found this candidate}}
283+
func overloadMismatchArgs(_: Int, a: () -> Void) -> Bool { return true}
284+
func overloadMismatchArgs(_: Int, x: Int = 0, a: () -> Void) -> Int { return 0 }
285285

286286
func overloadMismatchArgsLabel(_: Int, a: () -> Void) -> Bool { return true}
287287
func overloadMismatchArgsLabel(_: Int, x: Int = 0, b: () -> Void) -> Int { return 0 }
288288

289-
func overloadMismatchMultiArgs(_: Int, a: () -> Void) -> Bool { return true} // expected-note {{found this candidate}}
290-
func overloadMismatchMultiArgs(_: Int, x: Int = 0, y: Int = 1, a: () -> Void) -> Int { return 0 } // expected-note {{found this candidate}}
289+
func overloadMismatchMultiArgs(_: Int, a: () -> Void) -> Bool { return true}
290+
func overloadMismatchMultiArgs(_: Int, x: Int = 0, y: Int = 1, a: () -> Void) -> Int { return 0 }
291291

292292
func overloadMismatchMultiArgsLabel(_: Int, a: () -> Void) -> Bool { return true}
293293
func overloadMismatchMultiArgsLabel(_: Int, x: Int = 0, y: Int = 1, b: () -> Void) -> Int { return 0 }
294294

295-
func overloadMismatchMultiArgs2(_: Int, z: Int = 0, a: () -> Void) -> Bool { return true} // expected-note {{found this candidate}}
296-
func overloadMismatchMultiArgs2(_: Int, x: Int = 0, y: Int = 1, a: () -> Void) -> Int { return 0 } // expected-note {{found this candidate}}
295+
func overloadMismatchMultiArgs2(_: Int, z: Int = 0, a: () -> Void) -> Bool { return true}
296+
func overloadMismatchMultiArgs2(_: Int, x: Int = 0, y: Int = 1, a: () -> Void) -> Int { return 0 }
297297

298298
func overloadMismatchMultiArgs2Label(_: Int, z: Int = 0, a: () -> Void) -> Bool { return true}
299299
func overloadMismatchMultiArgs2Label(_: Int, x: Int = 0, y: Int = 1, b: () -> Void) -> Int { return 0 }
300300

301301
func testOverloadDefaultArgs() {
302-
let a = overloadMismatch {} // expected-error {{ambiguous use of 'overloadMismatch'}}
303-
_ = a as String
304-
let b = overloadMismatch() {} // expected-error {{ambiguous use of 'overloadMismatch'}}
305-
_ = b as String
306-
307-
let c = overloadMismatchLabel {} // expected-error {{ambiguous use of 'overloadMismatchLabel'}}
308-
// expected-note@-1 {{use an explicit argument label instead of a trailing closure to call 'overloadMismatchLabel(a:)'}} {{32-33=(a: }} {{35-35=)}}
309-
// expected-note@-2 {{use an explicit argument label instead of a trailing closure to call 'overloadMismatchLabel(x:b:)'}} {{32-33=(b: }} {{35-35=)}}
310-
_ = c as String
311-
let d = overloadMismatchLabel() {} // expected-error {{ambiguous use of 'overloadMismatchLabel'}}
312-
// expected-note@-1 {{use an explicit argument label instead of a trailing closure to call 'overloadMismatchLabel(a:)'}} {{33-35=a: }} {{37-37=)}}
313-
// expected-note@-2 {{use an explicit argument label instead of a trailing closure to call 'overloadMismatchLabel(x:b:)'}} {{33-35=b: }} {{37-37=)}}
314-
_ = d as String
315-
316-
let e = overloadMismatchArgs(0) {} // expected-error {{ambiguous use of 'overloadMismatchArgs'}}
317-
_ = e as String
318-
319-
let f = overloadMismatchArgsLabel(0) {} // expected-error {{ambiguous use of 'overloadMismatchArgsLabel'}}
320-
// expected-note@-1 {{use an explicit argument label instead of a trailing closure to call 'overloadMismatchArgsLabel(_:a:)'}} {{38-40=, a: }} {{42-42=)}}
321-
// expected-note@-2 {{use an explicit argument label instead of a trailing closure to call 'overloadMismatchArgsLabel(_:x:b:)'}} {{38-40=, b: }} {{42-42=)}}
322-
_ = f as String
323-
324-
let g = overloadMismatchMultiArgs(0) {} // expected-error {{ambiguous use of 'overloadMismatchMultiArgs'}}
325-
_ = g as String
326-
327-
let h = overloadMismatchMultiArgsLabel(0) {} // expected-error {{ambiguous use of 'overloadMismatchMultiArgsLabel'}}
328-
// expected-note@-1 {{use an explicit argument label instead of a trailing closure to call 'overloadMismatchMultiArgsLabel(_:a:)'}} {{43-45=, a: }} {{47-47=)}}
329-
// expected-note@-2 {{use an explicit argument label instead of a trailing closure to call 'overloadMismatchMultiArgsLabel(_:x:y:b:)'}} {{43-45=, b: }} {{47-47=)}}
330-
_ = h as String
331-
332-
let i = overloadMismatchMultiArgs2(0) {} // expected-error {{ambiguous use of 'overloadMismatchMultiArgs2'}}
333-
_ = i as String
334-
335-
let j = overloadMismatchMultiArgs2Label(0) {} // expected-error {{ambiguous use of 'overloadMismatchMultiArgs2Label'}}
336-
// expected-note@-1 {{use an explicit argument label instead of a trailing closure to call 'overloadMismatchMultiArgs2Label(_:z:a:)'}} {{44-46=, a: }} {{48-48=)}}
337-
// expected-note@-2 {{use an explicit argument label instead of a trailing closure to call 'overloadMismatchMultiArgs2Label(_:x:y:b:)'}} {{44-46=, b: }} {{48-48=)}}
338-
_ = j as String
302+
let a = overloadMismatch {}
303+
_ = a as String // expected-error {{cannot convert value of type 'Bool' to type 'String' in coercion}}
304+
let b = overloadMismatch() {}
305+
_ = b as String // expected-error {{cannot convert value of type 'Bool' to type 'String' in coercion}}
306+
307+
let c = overloadMismatchLabel {}
308+
_ = c as String // expected-error {{cannot convert value of type 'Bool' to type 'String' in coercion}}
309+
let d = overloadMismatchLabel() {}
310+
_ = d as String // expected-error {{cannot convert value of type 'Bool' to type 'String' in coercion}}
311+
312+
let e = overloadMismatchArgs(0) {}
313+
_ = e as String // expected-error {{cannot convert value of type 'Bool' to type 'String' in coercion}}
314+
315+
let f = overloadMismatchArgsLabel(0) {}
316+
_ = f as String // expected-error {{cannot convert value of type 'Bool' to type 'String' in coercion}}
317+
318+
let g = overloadMismatchMultiArgs(0) {}
319+
_ = g as String // expected-error {{cannot convert value of type 'Bool' to type 'String' in coercion}}
320+
321+
let h = overloadMismatchMultiArgsLabel(0) {}
322+
_ = h as String // expected-error {{cannot convert value of type 'Bool' to type 'String' in coercion}}
323+
324+
let i = overloadMismatchMultiArgs2(0) {}
325+
_ = i as String // expected-error {{cannot convert value of type 'Bool' to type 'String' in coercion}}
326+
327+
let j = overloadMismatchMultiArgs2Label(0) {}
328+
_ = j as String // expected-error {{cannot convert value of type 'Bool' to type 'String' in coercion}}
339329
}
340330

341331
func variadic(_: (() -> Void)...) {}
342332
func variadicLabel(closures: (() -> Void)...) {}
343333

344-
func variadicOverloadMismatch(_: (() -> Void)...) -> Bool { return true } // expected-note 2 {{found this candidate}}
345-
func variadicOverloadMismatch(x: Int = 0, _: (() -> Void)...) -> Int { return 0 } // expected-note 2 {{found this candidate}}
334+
func variadicOverloadMismatch(_: (() -> Void)...) -> Bool { return true }
335+
func variadicOverloadMismatch(x: Int = 0, _: (() -> Void)...) -> Int { return 0 }
346336

347-
func variadicOverloadMismatchLabel(a: (() -> Void)...) -> Bool { return true } // expected-note 2 {{found this candidate}}
348-
func variadicOverloadMismatchLabel(x: Int = 0, b: (() -> Void)...) -> Int { return 0 } // expected-note 2 {{found this candidate}}
337+
func variadicOverloadMismatchLabel(a: (() -> Void)...) -> Bool { return true }
338+
func variadicOverloadMismatchLabel(x: Int = 0, b: (() -> Void)...) -> Int { return 0 }
349339

350340
func variadicAndNonOverload(_: (() -> Void)) -> Bool { return false }
351341
func variadicAndNonOverload(_: (() -> Void)...) -> Int { return 0 }
@@ -362,15 +352,15 @@ func testVariadic() {
362352
variadicLabel() {}
363353
variadicLabel(closures: {}) {} // expected-error {{extra argument 'closures' in call}}
364354

365-
let a1 = variadicOverloadMismatch {} // expected-error {{ambiguous use of 'variadicOverloadMismatch'}}
366-
_ = a1 as String
367-
let a2 = variadicOverloadMismatch() {} // expected-error {{ambiguous use of 'variadicOverloadMismatch'}}
368-
_ = a2 as String
355+
let a1 = variadicOverloadMismatch {}
356+
_ = a1 as String // expected-error {{cannot convert value of type 'Bool' to type 'String' in coercion}}
357+
let a2 = variadicOverloadMismatch() {}
358+
_ = a2 as String // expected-error {{cannot convert value of type 'Bool' to type 'String' in coercion}}
369359

370-
let b1 = variadicOverloadMismatchLabel {} // expected-error {{ambiguous use of 'variadicOverloadMismatchLabel'}}
371-
_ = b1 as String
372-
let b2 = variadicOverloadMismatchLabel() {} // expected-error {{ambiguous use of 'variadicOverloadMismatchLabel'}}
373-
_ = b2 as String
360+
let b1 = variadicOverloadMismatchLabel {}
361+
_ = b1 as String // expected-error {{cannot convert value of type 'Bool' to type 'String' in coercion}}
362+
let b2 = variadicOverloadMismatchLabel() {}
363+
_ = b2 as String // expected-error {{cannot convert value of type 'Bool' to type 'String' in coercion}}
374364

375365
let c1 = variadicAndNonOverloadLabel {}
376366
_ = c1 as String // expected-error {{cannot convert value of type 'Bool' to type 'String'}}

test/Constraints/rdar36226874.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %target-swift-frontend -emit-sil -verify %s | %FileCheck %s
2+
3+
func foo(a: Int) {}
4+
func foo(q: String = "", a: Int) {}
5+
6+
// CHECK: function_ref @_T012rdar362268743foo1aySi_tF : $@convention(thin) (Int) -> ()
7+
foo(a: 42)
8+
9+
func bar(a: Int, c: Int) {}
10+
func bar(a: Int, b: Int = 0, c: Int) {}
11+
12+
// CHECK: function_ref @_T012rdar362268743bar1a1cySi_SitF : $@convention(thin) (Int, Int) -> ()
13+
bar(a: 0, c: 42)

0 commit comments

Comments
 (0)