File tree Expand file tree Collapse file tree 2 files changed +81
-0
lines changed
Expand file tree Collapse file tree 2 files changed +81
-0
lines changed Original file line number Diff line number Diff line change @@ -758,6 +758,29 @@ bool CompareDeclSpecializationRequest::evaluate(
758758 unsigned numParams1 = params1.size ();
759759 unsigned numParams2 = params2.size ();
760760
761+ // Handle the following situation:
762+ //
763+ // struct S {
764+ // func test() {}
765+ // static func test(_: S) {}
766+ // }
767+ //
768+ // Calling `S.test(s)` where `s` has a type `S` without any other context
769+ // should prefer a complete call to a static member over a partial
770+ // application of an instance once based on the choice of the base type.
771+ //
772+ // The behavior is consistent for double-applies as well i.e.
773+ // `S.test(s)()` if static method produced a function type it would be
774+ // preferred.
775+ if (decl1->isInstanceMember () != decl2->isInstanceMember () &&
776+ isa<FuncDecl>(decl1) && isa<FuncDecl>(decl2)) {
777+ auto selfTy = decl1->isInstanceMember () ? selfTy2 : selfTy1;
778+ auto params = decl1->isInstanceMember () ? params2 : params1;
779+ if (params.size () == 1 && params[0 ].getPlainType ()->isEqual (selfTy)) {
780+ return completeResult (!decl1->isInstanceMember ());
781+ }
782+ }
783+
761784 if (numParams1 > numParams2)
762785 return completeResult (false );
763786
Original file line number Diff line number Diff line change @@ -414,3 +414,61 @@ do {
414414 }
415415 }
416416}
417+
418+ do {
419+ struct S {
420+ func test( ) -> Int { 42 }
421+ static func test( _: S ... ) { }
422+
423+ func doubleApply( ) { }
424+ static func doubleApply( _: S ) -> ( ) -> Int { { 42 } }
425+ }
426+
427+ func test( s: S ) {
428+ let res1 = S . test ( s)
429+ // expected-warning@-1 {{constant 'res1' inferred to have type '()', which may be unexpected}}
430+ // expected-note@-2 {{add an explicit type annotation to silence this warning}}
431+ _ = res1
432+
433+ let useInstance = S . test ( s) ( )
434+ let _: Int = useInstance
435+
436+ let res2 = {
437+ S . test ( s)
438+ }
439+ let _: ( ) -> Void = res2
440+
441+ let _ = { ( ) async -> Void in
442+ _ = 42
443+ return S . test ( s)
444+ }
445+
446+ let res3 = S . doubleApply ( s)
447+ let _: ( ) -> Int = res3
448+
449+ let res4 = S . doubleApply ( s) ( )
450+ let _: Int = res4
451+
452+ let res5 = { S . doubleApply ( s) ( ) }
453+ let _: ( ) -> Int = res5
454+
455+ let res6 = {
456+ _ = 42
457+ return S . doubleApply ( s)
458+ }
459+ let _: ( ) -> Int = res6 ( )
460+ }
461+
462+ func testAsyncContext( s: S ) async {
463+ let res1 = S . test ( s)
464+ // expected-warning@-1 {{constant 'res1' inferred to have type '()', which may be unexpected}}
465+ // expected-note@-2 {{add an explicit type annotation to silence this warning}}
466+ _ = res1
467+
468+ let res2 = S . doubleApply ( s)
469+ let _: ( ) -> Int = res2
470+
471+ let res3 = S . doubleApply ( s) ( )
472+ let _: Int = res3
473+ }
474+ }
You can’t perform that action at this time.
0 commit comments