Why would a value type provide an unlabeled initializer from its own type?
Well, whatever. I think there’s a bug here, because SE-0213 seems fairly unambiguous about this always using the literal initializer, so it should not be considering failable initializers in optional context. If people want to separately pitch reverting SE-0213 because they misunderstood the proposal, they’re welcome to do so.
I actually wanted to make TimeOfDay(...)?.hour
an invalid syntax, but that would have resolved in source compatibility problem, that's why the decision was made to keep supporting it.
I think we should’ve talked about that. Presumably this was already only done under a new language compatibility version.
Yeah, that's exactly how it is.
I realized today that I'm using the Swift 5 compiler in Swift 4.2 mode, so I think this issue affects both syntax modes.
I don't know if that's relevant to @John_McCall's "new language compatibility version" comment.
This makes sense as this is (partly) a runtime behavior, so you get all bug fixes and new runtime behavior regardless of the language mode your project has.
I don't think there's any language-runtime involvement here. It should be totally determined by language compatibility mode.
Was the consensus there is a bug (or bugs) here?
- The behavior change affects Swift-4 source mode.
- The compiler's initializer selection is affected by the surrounding context (e.g. being part of an optional chain).
Also, should the compiler emit and error (or at least a warning) if you try to implement a no-label initializer along side a literal initializer? Allowing both results in really confusing behavior:
struct TimeOfDay: ExpressibleByStringLiteral {
init(_ string: String) {
print("using init(_:)")
}
init(stringLiteral: String) {
print("using init(stringLiteral:)")
}
}
TimeOfDay("00:00") // prints "using init(stringLiteral:)"
TimeOfDay.init("00:00") // prints "using init(_:)"
I think both (1) and (2) are bugs. I don't think that warning would be appropriate because it's common to have both coercion initializers and literal initializers.
I think if it's common to have both, we would need to revisit SE-0123, because that proposal makes it pretty difficult for both to coexist.
Edit: To clarify, I only meant the compiler should emit a warning if the no-label initializer has the same effective signature as the literal initializer. You would of course still be free to define init(_ x: SomeOtherType)
It took probably too long, but I finally filed SR-10816 for (1).
I'm unable to reproduce (2) anymore. The compiler appears to consistently choose the string literal initializer now. (Maybe I was using Xcode 10.2.0 before, vs 10.2.1 now?)