[swift-evolution] Disallow local parameter names in protocols

James Froggatt james.froggatt at me.com
Tue Jul 19 11:42:03 CDT 2016


Made a draft proposal to start this discussion, and help define the problem. I'm not too biased either way, this isn't a particularly major aspect of the language, but obviously the proposal has to justify the potential change to the language. This is something due for re-evaluation since Swift 3 removed the ‘first-argument hide-by-default’ rule, which now makes this simplification possible.

Hoping to get an idea of what people's opinions are on this, and the subject of local parameter names leaking to the user in general. Please let me know if my reasoning is flawed, anywhere.




## Introduction

Swift's current treatment of local parameter names is rather odd. They're hidden from the caller most of the timer, where an external parameter label is specified, but otherwise (if a ‘_’ is used), they actually leak out into Xcode's autocomplete. External labels are intended to add clarity, so the local names seem like they should be an implementation detail. Otherwise, why don't local names show up for labelled parameters, too?

The main point in the language affected by this ambiguity is in the protocol definition, where local names can be specified, but are only in any way useful for autocomplete when implementing the protocol, making them useless to the language itself. This proposal, if accepted, would simplify the language by removing the ability to declare local parameter names from protocols, reducing their function signatures to just the actual requirements - label and type.

## Motivation

Consider the following code:

````swift
protocol ExampleProtocol {

	func move(from source: Int, to destination: Int)
	
	func max(_ a: Int, _ b: Int) -> Int
	
	func find(_: String, in: String)
}

struct ExampleStruct1: ExampleProtocol {

	func move(from source: Int, to destination: Int) { return }
	
	func max(_ a: Int, _ b: Int) -> Int { return 0 }
	
	func find(_: String, in: String) { return }
}

//still conforms, despite differences to the protocol signature
struct ExampleStruct2: ExampleProtocol {

	func move(from: Int, to: Int) { return }
	
	func max(_ first: Int, _ second: Int) -> Int { return 0 }
	
	func find(_ substring: String, in string: String) { return }
}
````

ExampleStruct2 conforms to ExampleProtocol, yet clearly has some differences to the signatures defined in the protocol. In ExampleStruct2, its `move` function has no local parameter names, despite their presence in the protocol definition. Its `max` function has differing local names, and `find` has names which aren't present in the protocol.

In functions, it is the purpose of external parameter labels serve to add clarity to the call site. The local names become variables in the function's scope, and are generally invisible to the caller. While these local names can be declared in the protocol, they aren't enforced, and are effectively useless. A confused user may expect that this will enforce the local names, or otherwise specify a requirement, similar to other protocol semantics.

## Proposed solution

Remove the ability to specify local parameter names from protocols.

## Detailed design

Specification of local parameter names in protocols would trigger a compiler error, explaining that local parameter names are not enforced, with a fixit to remove the local name from the parameter list.

## Impact on existing code

This will break existing protocols which declare local parameter names, but should be easily fixable with the migrator, or the previously mentioned fixit.

## Alternatives considered

Leave protocols as they are now, or enforce local parameter names where specified.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160719/e6132a62/attachment.html>


More information about the swift-evolution mailing list