Skip to content

Commit

Permalink
Implement SE-0253 review feedback.
Browse files Browse the repository at this point in the history
Use `callFunction` instead of `call` as the call-syntax delegate method name.
Add trailing closure tests.
  • Loading branch information
dan-zheng committed May 17, 2019
1 parent 932f108 commit 4cce21f
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 57 deletions.
4 changes: 2 additions & 2 deletions include/swift/AST/Decl.h
Expand Up @@ -5958,8 +5958,8 @@ class FuncDecl : public AbstractFunctionDecl {
bool isConsuming() const {
return getSelfAccessKind() == SelfAccessKind::__Consuming;
}
bool isCallable() const {
return getName().str() == "call" && isInstanceMember();
bool isCallFunction() const {
return getName().str() == "callFunction" && isInstanceMember();
}

SelfAccessKind getSelfAccessKind() const {
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/KnownIdentifiers.def
Expand Up @@ -31,7 +31,7 @@ IDENTIFIER(Any)
IDENTIFIER(ArrayLiteralElement)
IDENTIFIER(atIndexedSubscript)
IDENTIFIER_(bridgeToObjectiveC)
IDENTIFIER(call)
IDENTIFIER(callFunction)
IDENTIFIER_WITH_NAME(code_, "_code")
IDENTIFIER(CodingKeys)
IDENTIFIER(combine)
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/CSApply.cpp
Expand Up @@ -7228,7 +7228,7 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
auto selected = solution.getOverloadChoice(cs.getConstraintLocator(loc));
auto choice = selected.choice;
auto *callMethod = dyn_cast<FuncDecl>(selected.choice.getDecl());
if (callMethod && callMethod->isCallable()) {
if (callMethod && callMethod->isCallFunction()) {
auto methodType =
simplifyType(selected.openedType)->castTo<AnyFunctionType>();
auto selfParam = callMethod->getImplicitSelfDecl();
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/CSDiag.cpp
Expand Up @@ -4804,7 +4804,7 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
auto hasCallMethods = nominal &&
llvm::any_of(nominal->getMembers(), [](Decl *member) {
auto funcDecl = dyn_cast<FuncDecl>(member);
return funcDecl && funcDecl->isCallable();
return funcDecl && funcDecl->isCallFunction();
});

// Diagnose @dynamicCallable errors.
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/CSSimplify.cpp
Expand Up @@ -5794,7 +5794,7 @@ ConstraintSystem::simplifyApplicableFnConstraint(
// Get all call methods of the nominal type.
// TODO: Consider caching?
SmallVector<FuncDecl *, 4> callMethods;
auto candidates = lookupMember(desugar2, DeclName(ctx.Id_call));
auto candidates = lookupMember(desugar2, DeclName(ctx.Id_callFunction));
for (auto entry : candidates) {
auto callMethod = dyn_cast<FuncDecl>(entry.getValueDecl());
if (!callMethod)
Expand Down
4 changes: 2 additions & 2 deletions test/Sema/Inputs/call_method_other_module.swift
@@ -1,11 +1,11 @@
public protocol Layer {
func call(_ input: Float) -> Float
func callFunction(_ input: Float) -> Float
}

public struct Dense {
public init() {}

public func call(_ input: Float) -> Float {
public func callFunction(_ input: Float) -> Float {
return input * 2
}
}
12 changes: 6 additions & 6 deletions test/Sema/call_method_generic.swift
@@ -1,22 +1,22 @@
// RUN: %target-typecheck-verify-swift

protocol P0 {
func call(x: Self)
func callFunction(x: Self)
}

struct ConcreteType {
func call<T, U>(_ x: T, _ y: U) -> (T, U) {
func callFunction<T, U>(_ x: T, _ y: U) -> (T, U) {
return (x, y)
}

func call<T, U>(_ fn: @escaping (T) -> U) -> (T) -> U {
func callFunction<T, U>(_ fn: @escaping (T) -> U) -> (T) -> U {
return fn
}
}

let concrete = ConcreteType()
_ = concrete(1, 3.0)
_ = concrete(concrete, concrete.call as ([Int], Float) -> ([Int], Float))
_ = concrete(concrete, concrete.callFunction as ([Int], Float) -> ([Int], Float))

func generic<T, U>(_ x: T, _ y: U) {
_ = concrete(x, x)
Expand All @@ -25,14 +25,14 @@ func generic<T, U>(_ x: T, _ y: U) {

struct GenericType<T : Collection> {
let collection: T
func call<U>(_ x: U) -> Bool where U == T.Element, U : Equatable {
func callFunction<U>(_ x: U) -> Bool where U == T.Element, U : Equatable {
return collection.contains(x)
}
}

// Test conditional conformance.
extension GenericType where T.Element : Numeric {
func call(initialValue: T.Element) -> T.Element {
func callFunction(initialValue: T.Element) -> T.Element {
return collection.reduce(initialValue, +)
}
}
Expand Down
22 changes: 11 additions & 11 deletions test/Sema/call_method_protocol.swift
@@ -1,8 +1,8 @@
// RUN: %target-typecheck-verify-swift

protocol P0 {
// expected-note @+1 {{protocol requires function 'call()' with type '() -> Missing'; do you want to add a stub?}}
func call() -> Self
// expected-note @+1 {{protocol requires function 'callFunction()' with type '() -> Missing'; do you want to add a stub?}}
func callFunction() -> Self
}
func testProtocol(_ x: P0) {
_ = x()
Expand All @@ -12,18 +12,18 @@ func testGeneric<T : P0>(_ x: T) {
}

protocol P1 {
func call() -> Self
func callFunction() -> Self
}
extension P1 {
// expected-note @+1 {{found this candidate}}
func call() -> Self {
func callFunction() -> Self {
return self
}
}
protocol P2 {}
extension P2 {
// expected-note @+1 {{found this candidate}}
func call(x: Int, y: Int) -> Int {
func callFunction(x: Int, y: Int) -> Int {
return x + y
}
}
Expand All @@ -32,13 +32,13 @@ extension P2 {
struct Missing : P0 {}
struct S0 : P0 {
@discardableResult
func call() -> S0 { return self }
func callFunction() -> S0 { return self }
}
let s0 = S0()
s0()

struct S1 : P1 {
func call() -> S1 { return self }
func callFunction() -> S1 { return self }
}

let s1 = S1()
Expand All @@ -47,13 +47,13 @@ _ = s1()()
struct Conforming : P0 & P1 & P2 {}
let conforming = Conforming()
_ = conforming(x: 1, y: 2)
_ = conforming().call(x:y:)(1, 2)
_ = conforming.call(x:y:)
_ = conforming.call // expected-error {{ambiguous use of 'call'}}
_ = conforming().callFunction(x:y:)(1, 2)
_ = conforming.callFunction(x:y:)
_ = conforming.callFunction // expected-error {{ambiguous use of 'callFunction'}}

protocol P3 {}
extension P3 {
func call() -> Self { return self }
func callFunction() -> Self { return self }
}
struct S3 : P3 {}

Expand Down
77 changes: 45 additions & 32 deletions test/Sema/call_method_simple.swift
@@ -1,7 +1,7 @@
// RUN: %target-typecheck-verify-swift

struct SimpleCallable {
func call(_ x: Float) -> Float {
func callFunction(_ x: Float) -> Float {
return x
}
}
Expand All @@ -21,11 +21,11 @@ let _: (Float) -> Float = foo

// Test direct `call` member references.

_ = foo.call(1)
_ = [1, 2, 3].map(foo.call)
_ = foo.call(foo(1))
_ = foo(foo.call(1))
let _: (Float) -> Float = foo.call
_ = foo.callFunction(1)
_ = [1, 2, 3].map(foo.callFunction)
_ = foo.callFunction(foo(1))
_ = foo(foo.callFunction(1))
let _: (Float) -> Float = foo.callFunction

func callable() -> SimpleCallable {
return SimpleCallable()
Expand All @@ -42,43 +42,56 @@ extension SimpleCallable {
_ = foo.foo(1)
_ = foo.bar()(1)
_ = callable()(1)
_ = [1, 2, 3].map(foo.foo.call)
_ = [1, 2, 3].map(foo.bar().call)
_ = [1, 2, 3].map(callable().call)
_ = [1, 2, 3].map(foo.foo.callFunction)
_ = [1, 2, 3].map(foo.bar().callFunction)
_ = [1, 2, 3].map(callable().callFunction)

struct MultipleArgsCallable {
func call(x: Int, y: Float) -> [Int] {
func callFunction(x: Int, y: Float) -> [Int] {
return [x]
}
}

let bar = MultipleArgsCallable()
_ = bar(x: 1, y: 1)
_ = bar.call(x: 1, y: 1)
_ = bar(x: bar.call(x: 1, y: 1)[0], y: 1)
_ = bar.call(x: bar(x: 1, y: 1)[0], y: 1)
_ = bar.callFunction(x: 1, y: 1)
_ = bar(x: bar.callFunction(x: 1, y: 1)[0], y: 1)
_ = bar.callFunction(x: bar(x: 1, y: 1)[0], y: 1)
_ = bar(1, 1) // expected-error {{missing argument labels 'x:y:' in call}}

struct Extended {}
extension Extended {
@discardableResult
func call() -> Extended {
func callFunction() -> Extended {
return self
}
}
var extended = Extended()
extended()().call()()
extended()().callFunction()()

struct TakesTrailingClosure {
func callFunction(_ fn: () -> Void) {
fn()
}
func callFunction(_ x: Int, label y: Float, _ fn: (Int, Float) -> Void) {
fn(x, y)
}
}
var takesTrailingClosure = TakesTrailingClosure()
takesTrailingClosure { print("Hi") }
takesTrailingClosure() { print("Hi") }
takesTrailingClosure(1, label: 2) { _ = Float($0) + $1 }

struct OptionalCallable {
func call() -> OptionalCallable? {
func callFunction() -> OptionalCallable? {
return self
}
}
var optional = OptionalCallable()
_ = optional()?.call()?()
_ = optional()?.callFunction()?()

struct Variadic {
func call(_ args: Int...) -> [Int] {
func callFunction(_ args: Int...) -> [Int] {
return args
}
}
Expand All @@ -88,35 +101,35 @@ _ = variadic(1, 2, 3)

struct Mutating {
var x: Int
mutating func call() {
mutating func callFunction() {
x += 1
}
}
func testMutating(_ x: Mutating, _ y: inout Mutating) {
_ = x() // expected-error {{cannot use mutating member on immutable value: 'x' is a 'let' constant}}
_ = x.call() // expected-error {{cannot use mutating member on immutable value: 'x' is a 'let' constant}}
_ = x.callFunction() // expected-error {{cannot use mutating member on immutable value: 'x' is a 'let' constant}}
_ = y()
_ = y.call()
_ = y.callFunction()
}

struct Inout {
func call(_ x: inout Int) {
func callFunction(_ x: inout Int) {
x += 5
}
}
func testInout(_ x: Inout, _ arg: inout Int) {
x(&arg)
x.call(&arg)
x.callFunction(&arg)
// TODO: Improve this error to match the error using a direct `call` member reference.
// expected-error @+2 {{cannot invoke 'x' with an argument list of type '(Int)'}}
// expected-error @+1 {{cannot call value of non-function type 'Inout'}}
x(arg)
// expected-error @+1 {{passing value of type 'Int' to an inout parameter requires explicit '&'}}
x.call(arg)
x.callFunction(arg)
}

struct Autoclosure {
func call(_ condition: @autoclosure () -> Bool,
func callFunction(_ condition: @autoclosure () -> Bool,
_ message: @autoclosure () -> String) {
if condition() {
print(message())
Expand All @@ -129,10 +142,10 @@ func testAutoclosure(_ x: Autoclosure) {
}

struct Throwing {
func call() throws -> Throwing {
func callFunction() throws -> Throwing {
return self
}
func call(_ f: () throws -> ()) rethrows {
func callFunction(_ f: () throws -> ()) rethrows {
try f()
}
}
Expand All @@ -145,7 +158,7 @@ enum BinaryOperation {
case add, subtract, multiply, divide
}
extension BinaryOperation {
func call(_ lhs: Float, _ rhs: Float) -> Float {
func callFunction(_ lhs: Float, _ rhs: Float) -> Float {
switch self {
case .add: return lhs + rhs
case .subtract: return lhs - rhs
Expand All @@ -157,12 +170,12 @@ extension BinaryOperation {
_ = BinaryOperation.add(1, 2)

class BaseClass {
func call() -> Self {
func callFunction() -> Self {
return self
}
}
class SubClass : BaseClass {
override func call() -> Self {
override func callFunction() -> Self {
return self
}
}
Expand All @@ -173,10 +186,10 @@ func testIUO(a: SimpleCallable!, b: MultipleArgsCallable!, c: Extended!,
_ = a(1)
_ = b(x: 1, y: 1)
_ = c()
_ = d()?.call()?()
_ = d()?.callFunction()?()
_ = e()
_ = e(1, 2, 3)
// FIXME(TF-444): `mutating func call` and IUO doesn't work.
// FIXME(TF-444): `mutating func callFunction` and IUO doesn't work.
// _ = f()
_ = g(&inoutInt)
_ = try? h()
Expand Down

0 comments on commit 4cce21f

Please sign in to comment.