Xiaodi has captured my views on the subject fairly well, although I have a couple of comments to add.
Having only been turned on initially in Swift 4.1, the near-miss diagnostics still need a bit of tuning to see if they can address the problem "enough". I do think we're close enough that it doesn't make sense to add a new keyword (or several keywords!) to an already-crowded space. The tools could also do better at handling missing required members, but as Xiaodi says, this will improve over time.
I do think we should tackle the disambiguation problem when there are two protocols with the same requirement. I don't think it comes up often, but the lack of a disambiguation mechanism when it does happen bothers me. Specifically, consider this example:
protocol P {
func foo()
}
protocol Q {
func foo()
}
struct X { }
extension X: P {
func foo() { ... }
}
extension X: Q {
func foo() { ... } // error: redeclaration of 'foo', so I can't have P's foo and Q's foo be different
}
My proposal is that one can qualify the declaration to specify which requirement it is satisfying. Such a method is only reference able via the protocol:
extension X: P {
func P.foo() { ... } // only used to satisfy the "foo" requirement of P
}
extension X: Q {
func Q.foo() { ... } // only used to satisfy the "foo" requirement of Q
}
Note that we've eliminated the ambiguity, but we've also provided a specific mechanism by which we can state our precise intent to satisfy a particular requirement. It's better than a keyword because we've stated which protocol we're referring to, so it's clearer. It also helps fill in the gaps where near-miss checking doesn't work so well. For example, near-miss checking depends somewhat on the convention that one writes a new extension for each protocol conformance. However, you might not be able to do that if your conformance relies on something that must be written in the main type definition, such as a stored property or a required initializer. For example:
protocol Initable {
init()
}
protocol Name {
var name: String { get set }
}
class C : Initable, Name {
var name: String // can't move this to an extension!
required init() { } // can't move this to an extension!
}
We can't benefit from near-miss checking when we can't move those conformances to extensions, but we could be more specific with my proposal:
class C : Initable, Name {
var Name.name: String // can't move this to an extension!
required Initable.init() { } // can't move this to an extension!
}
Doug