[Proposal draft] Disallow Optionals in String Interpolation Segments


(Harlan Haskins) #1

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a proposal to mitigate something that's burned us all since Swift 1. We'd love some feedback!

It's available here: https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments
Proposal: SE-NNNN
Authors: Harlan Haskins, Julio Carrettoni, Robert Widmann
Review Manager: TBD
Status: Awaiting revie
Introduction

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Swift-evolution thread: Discussion thread topic for that proposal

Motivation

The Swift Programming Language defines string interpolation segments as "a way to construct a new String value from a mix of constants, variables, literals, and expressions". There is one type that runs counter to this definition: Optional. The .none case in particular is used to indicate the absence of a value. Moreover, its inclusion in interpolation segments leads to the dreaded "nil" in output that is often fed to UI elements. Even barring that, interpolating a non-nil optional value yields "Optional("value")", a result that is not useful even in logged output.

Given that the Optional type is never fit for display to the end user, and can often be a surprising find in the console, we propose that requesting an Optional's debug description be an explicit act. This proposal now requires a warning when using an expression of Optional type within a string interpolation segment.

Proposed solution

The user will be warned after attempting to use an expression with type Optional<T> in a string interpolation segment. They will then be offered a fixit suggesting they explicitly request the debugDescription of the Optional value instead.

Detailed design

Semantic analysis currently does not do much but guarantee the well-formedness of expressions in interpolation segments. These are then fed directly to String.init(stringInterpolationSegment:) and are run through the runtime reflection system to generate a description. Semantic analysis will be tweaked to inspect the result of solving an interpolation segment for an Optional and will offer a fixit in that case.

Impact on existing code

As this is a warning, code written before this proposal will continue to compile and run with the same semantics as before. Authors of code that makes use of this unsafe pattern will be offered a migration path to the safer, more explicit form.

Alternatives considered

A fixit that suggests a default value be inserted would be entirely appropriate (following the style of the fixit introduced in SE-0140).

Forbidding this pattern by hard error would make this proposal a breaking change that is out of scope for this stage of Swift's development.

A fixit that introduces a force-unwrapping would technically work as well, however it would be fixing a dangerous operation with yet another dangerous operation.

···

Sent from my iPad


(Joe Groff) #2

We now emit a warning whenever an optional is used as an Any. I disagree that this should be an error, but it seems reasonable to warn (if we don't already thanks to the 'Any' warning).

-Joe

···

On Oct 3, 2016, at 10:52 AM, Harlan Haskins via swift-evolution <swift-evolution@swift.org> wrote:

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a proposal to mitigate something that's burned us all since Swift 1. We'd love some feedback!

It's available here: https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments

Proposal: SE-NNNN <https://gist.github.com/harlanhaskins/NNNN-filename.md>
Authors: Harlan Haskins <https://github.com/harlanhaskins>, Julio Carrettoni <https://github.com/Julioacarrettoni>, Robert Widmann <https://github.com/CodaFi>
Review Manager: TBD
Status: Awaiting revie
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#introduction>Introduction

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Swift-evolution thread: Discussion thread topic for that proposal <https://lists.swift.org/pipermail/swift-evolution/>
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#motivation>Motivation

The Swift Programming Language defines string interpolation segments as "a way to construct a new String value from a mix of constants, variables, literals, and expressions". There is one type that runs counter to this definition: Optional. The .none case in particular is used to indicate the absence of a value. Moreover, its inclusion in interpolation segments leads to the dreaded "nil" in output that is often fed to UI elements. Even barring that, interpolating a non-nil optional value yields "Optional("value")", a result that is not useful even in logged output.

Given that the Optional type is never fit for display to the end user, and can often be a surprising find in the console, we propose that requesting an Optional's debug description be an explicit act. This proposal now requires a warning when using an expression of Optional type within a string interpolation segment.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#proposed-solution>Proposed solution

The user will be warned after attempting to use an expression with type Optional<T> in a string interpolation segment. They will then be offered a fixit suggesting they explicitly request the debugDescription of the Optional value instead.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#detailed-design>Detailed design

Semantic analysis currently does not do much but guarantee the well-formedness of expressions in interpolation segments. These are then fed directly to String.init(stringInterpolationSegment:) and are run through the runtime reflection system to generate a description. Semantic analysis will be tweaked to inspect the result of solving an interpolation segment for an Optional and will offer a fixit in that case.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#impact-on-existing-code>Impact on existing code

As this is a warning, code written before this proposal will continue to compile and run with the same semantics as before. Authors of code that makes use of this unsafe pattern will be offered a migration path to the safer, more explicit form.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#alternatives-considered>Alternatives considered

A fixit that suggests a default value be inserted would be entirely appropriate (following the style of the fixit introduced in SE-0140 <https://github.com/apple/swift-evolution/blob/master/proposals/0140-bridge-optional-to-nsnull.md>).

Forbidding this pattern by hard error would make this proposal a breaking change that is out of scope for this stage of Swift's development.

A fixit that introduces a force-unwrapping would technically work as well, however it would be fixing a dangerous operation with yet another dangerous operation.

Sent from my iPad
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Keith Smiley) #3

+1 to this warning. We've been hit by this bug a bunch of times. Especially when
optionality of properties have been in flux.

Just yesterday: https://twitter.com/zefhous/status/782783999663943680

···

--
Keith Smiley

On 10/03, Harlan Haskins via swift-evolution wrote:

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a proposal to mitigate something that's burned us all since Swift 1. We'd love some feedback!

It's available here: https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments
Proposal: SE-NNNN
Authors: Harlan Haskins, Julio Carrettoni, Robert Widmann
Review Manager: TBD
Status: Awaiting revie
Introduction

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Swift-evolution thread: Discussion thread topic for that proposal

Motivation

The Swift Programming Language defines string interpolation segments as "a way to construct a new String value from a mix of constants, variables, literals, and expressions". There is one type that runs counter to this definition: Optional. The .none case in particular is used to indicate the absence of a value. Moreover, its inclusion in interpolation segments leads to the dreaded "nil" in output that is often fed to UI elements. Even barring that, interpolating a non-nil optional value yields "Optional("value")", a result that is not useful even in logged output.

Given that the Optional type is never fit for display to the end user, and can often be a surprising find in the console, we propose that requesting an Optional's debug description be an explicit act. This proposal now requires a warning when using an expression of Optional type within a string interpolation segment.

Proposed solution

The user will be warned after attempting to use an expression with type Optional<T> in a string interpolation segment. They will then be offered a fixit suggesting they explicitly request the debugDescription of the Optional value instead.

Detailed design

Semantic analysis currently does not do much but guarantee the well-formedness of expressions in interpolation segments. These are then fed directly to String.init(stringInterpolationSegment:) and are run through the runtime reflection system to generate a description. Semantic analysis will be tweaked to inspect the result of solving an interpolation segment for an Optional and will offer a fixit in that case.

Impact on existing code

As this is a warning, code written before this proposal will continue to compile and run with the same semantics as before. Authors of code that makes use of this unsafe pattern will be offered a migration path to the safer, more explicit form.

Alternatives considered

A fixit that suggests a default value be inserted would be entirely appropriate (following the style of the fixit introduced in SE-0140).

Forbidding this pattern by hard error would make this proposal a breaking change that is out of scope for this stage of Swift's development.

A fixit that introduces a force-unwrapping would technically work as well, however it would be fixing a dangerous operation with yet another dangerous operation.

Sent from my iPad

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Harlan Haskins) #4

Unfortunately, Optional-to-Any does not currently hit this case because IIRC it doesn't promote to Any in an interpolation segment. I tested this with a ToT build yesterday.

- Harlan

···

On Oct 3, 2016, at 1:57 PM, Joe Groff <jgroff@apple.com> wrote:

We now emit a warning whenever an optional is used as an Any. I disagree that this should be an error, but it seems reasonable to warn (if we don't already thanks to the 'Any' warning).

-Joe

On Oct 3, 2016, at 10:52 AM, Harlan Haskins via swift-evolution <swift-evolution@swift.org> wrote:

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a proposal to mitigate something that's burned us all since Swift 1. We'd love some feedback!

It's available here: https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments

Proposal: SE-NNNN
Authors: Harlan Haskins, Julio Carrettoni, Robert Widmann
Review Manager: TBD
Status: Awaiting revie
Introduction

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Swift-evolution thread: Discussion thread topic for that proposal

Motivation

The Swift Programming Language defines string interpolation segments as "a way to construct a new String value from a mix of constants, variables, literals, and expressions". There is one type that runs counter to this definition: Optional. The .none case in particular is used to indicate the absence of a value. Moreover, its inclusion in interpolation segments leads to the dreaded "nil" in output that is often fed to UI elements. Even barring that, interpolating a non-nil optional value yields "Optional("value")", a result that is not useful even in logged output.

Given that the Optional type is never fit for display to the end user, and can often be a surprising find in the console, we propose that requesting an Optional's debug description be an explicit act. This proposal now requires a warning when using an expression of Optional type within a string interpolation segment.

Proposed solution

The user will be warned after attempting to use an expression with type Optional<T> in a string interpolation segment. They will then be offered a fixit suggesting they explicitly request the debugDescription of the Optional value instead.

Detailed design

Semantic analysis currently does not do much but guarantee the well-formedness of expressions in interpolation segments. These are then fed directly to String.init(stringInterpolationSegment:) and are run through the runtime reflection system to generate a description. Semantic analysis will be tweaked to inspect the result of solving an interpolation segment for an Optional and will offer a fixit in that case.

Impact on existing code

As this is a warning, code written before this proposal will continue to compile and run with the same semantics as before. Authors of code that makes use of this unsafe pattern will be offered a migration path to the safer, more explicit form.

Alternatives considered

A fixit that suggests a default value be inserted would be entirely appropriate (following the style of the fixit introduced in SE-0140).

Forbidding this pattern by hard error would make this proposal a breaking change that is out of scope for this stage of Swift's development.

A fixit that introduces a force-unwrapping would technically work as well, however it would be fixing a dangerous operation with yet another dangerous operation.

Sent from my iPad
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Lily Ballard) #5

Is there any way we could instead allow Optionals but just print them
the way we print ImplicitlyUnwrappedOptionals? That's almost always how
I want my Optionals to work when interpolating. To be specific, this
means for .some(x) we just print x, and for .none we print "nil".

-Kevin

···

On Mon, Oct 3, 2016, at 10:52 AM, Harlan Haskins via swift-evolution wrote:

Swift developers frequently use string interpolation as a convenient,
concise syntax for interweaving variable values with strings. The
interpolation machinery, however, has surprising behavior in one
specific case: Optional<T>. If a user puts an optional value into a
string interpolation segment, it will insert either
"Optional("value")" or "nil" in the resulting string. Neither of these
is particularly desirable, so we propose a warning and fix-it to
surface solutions to these potential mistakes.


(Charlie Monroe) #6

I've already suggested this quite some time back and was told that this doesn't need to go through evolution. It's filed here: https://bugs.swift.org/browse/SR-1882

Unfortunately, I haven't had time to look into it myself and I'm unlikely to have the time anytime soon...

···

On Oct 3, 2016, at 7:52 PM, Harlan Haskins via swift-evolution <swift-evolution@swift.org> wrote:

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a proposal to mitigate something that's burned us all since Swift 1. We'd love some feedback!

It's available here: https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments

Proposal: SE-NNNN <https://gist.github.com/harlanhaskins/NNNN-filename.md>
Authors: Harlan Haskins <https://github.com/harlanhaskins>, Julio Carrettoni <https://github.com/Julioacarrettoni>, Robert Widmann <https://github.com/CodaFi>
Review Manager: TBD
Status: Awaiting revie
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#introduction>Introduction

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Swift-evolution thread: Discussion thread topic for that proposal <https://lists.swift.org/pipermail/swift-evolution/>
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#motivation>Motivation

The Swift Programming Language defines string interpolation segments as "a way to construct a new String value from a mix of constants, variables, literals, and expressions". There is one type that runs counter to this definition: Optional. The .none case in particular is used to indicate the absence of a value. Moreover, its inclusion in interpolation segments leads to the dreaded "nil" in output that is often fed to UI elements. Even barring that, interpolating a non-nil optional value yields "Optional("value")", a result that is not useful even in logged output.

Given that the Optional type is never fit for display to the end user, and can often be a surprising find in the console, we propose that requesting an Optional's debug description be an explicit act. This proposal now requires a warning when using an expression of Optional type within a string interpolation segment.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#proposed-solution>Proposed solution

The user will be warned after attempting to use an expression with type Optional<T> in a string interpolation segment. They will then be offered a fixit suggesting they explicitly request the debugDescription of the Optional value instead.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#detailed-design>Detailed design

Semantic analysis currently does not do much but guarantee the well-formedness of expressions in interpolation segments. These are then fed directly to String.init(stringInterpolationSegment:) and are run through the runtime reflection system to generate a description. Semantic analysis will be tweaked to inspect the result of solving an interpolation segment for an Optional and will offer a fixit in that case.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#impact-on-existing-code>Impact on existing code

As this is a warning, code written before this proposal will continue to compile and run with the same semantics as before. Authors of code that makes use of this unsafe pattern will be offered a migration path to the safer, more explicit form.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#alternatives-considered>Alternatives considered

A fixit that suggests a default value be inserted would be entirely appropriate (following the style of the fixit introduced in SE-0140 <https://github.com/apple/swift-evolution/blob/master/proposals/0140-bridge-optional-to-nsnull.md>).

Forbidding this pattern by hard error would make this proposal a breaking change that is out of scope for this stage of Swift's development.

A fixit that introduces a force-unwrapping would technically work as well, however it would be fixing a dangerous operation with yet another dangerous operation.

Sent from my iPad
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Robert Widmann) #7

Because the initializer here doesn’t take Any, it takes <T>.

~Robert Widmann

···

On Oct 3, 2016, at 2:00 PM, Harlan Haskins via swift-evolution <swift-evolution@swift.org> wrote:

Unfortunately, Optional-to-Any does not currently hit this case because IIRC it doesn't promote to Any in an interpolation segment. I tested this with a ToT build yesterday.

- Harlan

On Oct 3, 2016, at 1:57 PM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

We now emit a warning whenever an optional is used as an Any. I disagree that this should be an error, but it seems reasonable to warn (if we don't already thanks to the 'Any' warning).

-Joe

On Oct 3, 2016, at 10:52 AM, Harlan Haskins via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a proposal to mitigate something that's burned us all since Swift 1. We'd love some feedback!

It's available here: https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments

Proposal: SE-NNNN <https://gist.github.com/harlanhaskins/NNNN-filename.md>
Authors: Harlan Haskins <https://github.com/harlanhaskins>, Julio Carrettoni <https://github.com/Julioacarrettoni>, Robert Widmann <https://github.com/CodaFi>
Review Manager: TBD
Status: Awaiting revie
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#introduction>Introduction

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Swift-evolution thread: Discussion thread topic for that proposal <https://lists.swift.org/pipermail/swift-evolution/>
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#motivation>Motivation

The Swift Programming Language defines string interpolation segments as "a way to construct a new String value from a mix of constants, variables, literals, and expressions". There is one type that runs counter to this definition: Optional. The .none case in particular is used to indicate the absence of a value. Moreover, its inclusion in interpolation segments leads to the dreaded "nil" in output that is often fed to UI elements. Even barring that, interpolating a non-nil optional value yields "Optional("value")", a result that is not useful even in logged output.

Given that the Optional type is never fit for display to the end user, and can often be a surprising find in the console, we propose that requesting an Optional's debug description be an explicit act. This proposal now requires a warning when using an expression of Optional type within a string interpolation segment.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#proposed-solution>Proposed solution

The user will be warned after attempting to use an expression with type Optional<T> in a string interpolation segment. They will then be offered a fixit suggesting they explicitly request the debugDescription of the Optional value instead.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#detailed-design>Detailed design

Semantic analysis currently does not do much but guarantee the well-formedness of expressions in interpolation segments. These are then fed directly to String.init(stringInterpolationSegment:) and are run through the runtime reflection system to generate a description. Semantic analysis will be tweaked to inspect the result of solving an interpolation segment for an Optional and will offer a fixit in that case.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#impact-on-existing-code>Impact on existing code

As this is a warning, code written before this proposal will continue to compile and run with the same semantics as before. Authors of code that makes use of this unsafe pattern will be offered a migration path to the safer, more explicit form.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#alternatives-considered>Alternatives considered

A fixit that suggests a default value be inserted would be entirely appropriate (following the style of the fixit introduced in SE-0140 <https://github.com/apple/swift-evolution/blob/master/proposals/0140-bridge-optional-to-nsnull.md>).

Forbidding this pattern by hard error would make this proposal a breaking change that is out of scope for this stage of Swift's development.

A fixit that introduces a force-unwrapping would technically work as well, however it would be fixing a dangerous operation with yet another dangerous operation.

Sent from my iPad
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Jordan Rose) #8

We had this at one point, but we took it out because people would forget to test the nil case. I think `?? ""` or `?? nil` really is the best answer here.

Jordan

···

On Oct 3, 2016, at 14:41, Kevin Ballard via swift-evolution <swift-evolution@swift.org> wrote:

On Mon, Oct 3, 2016, at 10:52 AM, Harlan Haskins via swift-evolution wrote:

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Is there any way we could instead allow Optionals but just print them the way we print ImplicitlyUnwrappedOptionals? That's almost always how I want my Optionals to work when interpolating. To be specific, this means for .some(x) we just print x, and for .none we print "nil".


(Lily Ballard) #9

I assume you meant that as a reply to me?

The problem is twofold:

1. Printing the value without adornment, or "nil" for nil, is a very
   common thing to want to do and we shouldn't have to write code like
   `\(x.map(String.init(describing:)) ?? "nil")` to accomplish it.
2. Due to the changes made to IUOs, if you use a IUO in a string
   interpolation, previously it would print as desired (either the value
   or the string `"nil"`) but now it prints as Optional (e.g. with the
   `"Optional(…)"` wrapper).

-Kevin

Under our proposal you can return to the old semantics of printing
nil with an explicit optional cast - one which we will offer to
insert for you.

Otherwise if you actually intend for a default value that value would
have type Int, not String. Under the current regime if you want to
print something custom the for nil the way you've got it now you're
going to have to go through the reflecting initializer anyway so I
don't see a problem here.

~Robert Widmann

2016/10/03 19:25、Charlie Monroe via swift-evolution <swift-
evolution@swift.org> のメッセージ:

I've already suggested this quite some time back and was told that
this doesn't need to go through evolution. It's filed here:
https://bugs.swift.org/browse/SR-1882

Unfortunately, I haven't had time to look into it myself and I'm
unlikely to have the time anytime soon...

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a
proposal to mitigate something that's burned us all since Swift 1.
We'd love some feedback!

It's available here:
https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments

* Proposal: SE-NNNN[1]
* Authors: Harlan Haskins[2], Julio Carrettoni[3], Robert
   Widmann[4]
* Review Manager: TBD
* Status: Awaiting revie
Introduction
Swift developers frequently use string interpolation as a
convenient, concise syntax for interweaving variable values with
strings. The interpolation machinery, however, has surprising
behavior in one specific case: Optional<T>. If a user puts an
optional value into a string interpolation segment, it will insert
either "Optional("value")" or "nil" in the resulting string. Neither
of these is particularly desirable, so we propose a warning and fix-
it to surface solutions to these potential mistakes.
Swift-evolution thread: Discussion thread topic for that proposal[5]
Motivation
*The Swift Programming Language* defines string interpolation
segments as "a way to construct a new String value from a mix of
constants, variables, literals, and expressions". There is one type
that runs counter to this definition: Optional. The .none case in
particular is used to indicate the absence of a value. Moreover, its
inclusion in interpolation segments leads to the dreaded "nil" in
output that is often fed to UI elements. Even barring that,
interpolating a non-nil optional value yields "Optional("value")", a
result that is not useful even in logged output.
Given that the Optional type is never fit for display to the end
user, and can often be a surprising find in the console, we propose
that requesting an Optional's debug description be an explicit act.
This proposal now requires a warning when using an expression of
Optional type within a string interpolation segment.
Proposed solution
The user will be warned after attempting to use an expression with
type Optional<T> in a string interpolation segment. They will then
be offered a fixit suggesting they explicitly request the
debugDescription of the Optional value instead.
Detailed design
Semantic analysis currently does not do much but guarantee the well-
formedness of expressions in interpolation segments. These are then
fed directly to String.init(stringInterpolationSegment:) and are run
through the runtime reflection system to generate a description.
Semantic analysis will be tweaked to inspect the result of solving
an interpolation segment for an Optional and will offer a fixit in
that case.
Impact on existing code
As this is a warning, code written before this proposal will
continue to compile and run with the same semantics as before.
Authors of code that makes use of this unsafe pattern will be
offered a migration path to the safer, more explicit form.
Alternatives considered

* A fixit that suggests a default value be inserted would be
   entirely appropriate (following the style of the fixit introduced
   in SE-0140[6]).

* Forbidding this pattern by hard error would make this proposal a
   breaking change that is out of scope for this stage of Swift's
   development.

* A fixit that introduces a force-unwrapping would technically work
   as well, however it would be fixing a dangerous operation with
   yet another dangerous operation.

Sent from my iPad
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_________________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Links:

  1. https://gist.github.com/harlanhaskins/NNNN-filename.md
  2. https://github.com/harlanhaskins
  3. https://github.com/Julioacarrettoni
  4. https://github.com/CodaFi
  5. https://lists.swift.org/pipermail/swift-evolution/
  6. https://github.com/apple/swift-evolution/blob/master/proposals/0140-bridge-optional-to-nsnull.md

···

On Mon, Oct 3, 2016, at 05:43 PM, Robert Widmann via swift-evolution wrote:

On Oct 3, 2016, at 7:52 PM, Harlan Haskins via swift-evolution <swift- >>> evolution@swift.org> wrote:


(Lily Ballard) #10

I assume you meant that as a reply to me?

The problem is twofold:

1. Printing the value without adornment, or "nil" for nil, is a
   very common thing to want to do and we shouldn't have to write
   code like `\(x.map(String.init(describing:)) ?? "nil")` to
   accomplish it.

My point is before you were unable to do this without the ‘uglyness’
presented here anyway [you would have gotten “Optional(“value”)”], so
I don’t see the point of raising this concern. If you want the old
behavior, just ask for it with an explicit cast or
`.debugDescription`.

This proposal was done because the current behavior of Optionals in
string interpolation isn't very useful for most people. You're proposing
banning it outright (with an escape hatch to recover the current
behavior). I'm saying that, since it isn't very useful for most people,
instead of banning it we could make it useful.

-Kevin

2. Due to the changes made to IUOs, if you use a IUO in a string
   interpolation, previously it would print as desired (either the
   value or the string `"nil"`) but now it prints as Optional (e.g.
   with the `"Optional(…)"` wrapper).

IUOs are not in the scope for this proposal, but I get your point.

-Kevin

Under our proposal you can return to the old semantics of printing
nil with an explicit optional cast - one which we will offer to
insert for you.

Otherwise if you actually intend for a default value that value
would have type Int, not String. Under the current regime if you
want to print something custom the for nil the way you've got it now
you're going to have to go through the reflecting initializer anyway
so I don't see a problem here.

~Robert Widmann

2016/10/03 19:25、Charlie Monroe via swift-evolution <swift-
evolution@swift.org> のメッセージ:

I've already suggested this quite some time back and was told that
this doesn't need to go through evolution. It's filed here:
https://bugs.swift.org/browse/SR-1882

Unfortunately, I haven't had time to look into it myself and I'm
unlikely to have the time anytime soon...

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a
proposal to mitigate something that's burned us all since Swift 1.
We'd love some feedback!

It's available here:
https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments

* Proposal: SE-NNNN[1]
* Authors: Harlan Haskins[2], Julio Carrettoni[3], Robert
   Widmann[4]
* Review Manager: TBD
* Status: Awaiting revie
Introduction
Swift developers frequently use string interpolation as a
convenient, concise syntax for interweaving variable values with
strings. The interpolation machinery, however, has surprising
behavior in one specific case: Optional<T>. If a user puts an
optional value into a string interpolation segment, it will insert
either "Optional("value")" or "nil" in the resulting string.
Neither of these is particularly desirable, so we propose a
warning and fix-it to surface solutions to these potential
mistakes.
Swift-evolution thread: Discussion thread topic for that
proposal[5]
Motivation
*The Swift Programming Language* defines string interpolation
segments as "a way to construct a new String value from a mix of
constants, variables, literals, and expressions". There is one
type that runs counter to this definition: Optional. The .none
case in particular is used to indicate the absence of a value.
Moreover, its inclusion in interpolation segments leads to the
dreaded "nil" in output that is often fed to UI elements. Even
barring that, interpolating a non-nil optional value yields
"Optional("value")", a result that is not useful even in logged
output.
Given that the Optional type is never fit for display to the end
user, and can often be a surprising find in the console, we
propose that requesting an Optional's debug description be an
explicit act. This proposal now requires a warning when using an
expression of Optional type within a string interpolation segment.
Proposed solution
The user will be warned after attempting to use an expression with
type Optional<T> in a string interpolation segment. They will then
be offered a fixit suggesting they explicitly request the
debugDescription of the Optional value instead.
Detailed design
Semantic analysis currently does not do much but guarantee the well-
formedness of expressions in interpolation segments. These are
then fed directly to String.init(stringInterpolationSegment:) and
are run through the runtime reflection system to generate a
description. Semantic analysis will be tweaked to inspect the
result of solving an interpolation segment for an Optional and
will offer a fixit in that case.
Impact on existing code
As this is a warning, code written before this proposal will
continue to compile and run with the same semantics as before.
Authors of code that makes use of this unsafe pattern will be
offered a migration path to the safer, more explicit form.
Alternatives considered

* A fixit that suggests a default value be inserted would be
   entirely appropriate (following the style of the fixit
   introduced in SE-0140[6]).

* Forbidding this pattern by hard error would make this proposal
   a breaking change that is out of scope for this stage of
   Swift's development.

* A fixit that introduces a force-unwrapping would technically
   work as well, however it would be fixing a dangerous operation
   with yet another dangerous operation.

Sent from my iPad
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_________________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Links:

  1. https://gist.github.com/harlanhaskins/NNNN-filename.md
  2. https://github.com/harlanhaskins
  3. https://github.com/Julioacarrettoni
  4. https://github.com/CodaFi
  5. https://lists.swift.org/pipermail/swift-evolution/
  6. https://github.com/apple/swift-evolution/blob/master/proposals/0140-bridge-optional-to-nsnull.md

···

On Mon, Oct 3, 2016, at 06:49 PM, Robert Widmann wrote:

On Oct 3, 2016, at 8:49 PM, Kevin Ballard via swift-evolution <swift- >> evolution@swift.org> wrote:
On Mon, Oct 3, 2016, at 05:43 PM, Robert Widmann via swift- >> evolution wrote:

On Oct 3, 2016, at 7:52 PM, Harlan Haskins via swift-evolution <swift- >>>>> evolution@swift.org> wrote:


(Robert Widmann) #11

Under our proposal you can return to the old semantics of printing nil with an explicit optional cast - one which we will offer to insert for you.

Otherwise if you actually intend for a default value that value would have type Int, not String. Under the current regime if you want to print something custom the for nil the way you've got it now you're going to have to go through the reflecting initializer anyway so I don't see a problem here.

~Robert Widmann

2016/10/03 19:25、Charlie Monroe via swift-evolution <swift-evolution@swift.org> のメッセージ:

···

I've already suggested this quite some time back and was told that this doesn't need to go through evolution. It's filed here: https://bugs.swift.org/browse/SR-1882

Unfortunately, I haven't had time to look into it myself and I'm unlikely to have the time anytime soon...

On Oct 3, 2016, at 7:52 PM, Harlan Haskins via swift-evolution <swift-evolution@swift.org> wrote:

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a proposal to mitigate something that's burned us all since Swift 1. We'd love some feedback!

It's available here: https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments
Proposal: SE-NNNN
Authors: Harlan Haskins, Julio Carrettoni, Robert Widmann
Review Manager: TBD
Status: Awaiting revie
Introduction

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Swift-evolution thread: Discussion thread topic for that proposal

Motivation

The Swift Programming Language defines string interpolation segments as "a way to construct a new String value from a mix of constants, variables, literals, and expressions". There is one type that runs counter to this definition: Optional. The .none case in particular is used to indicate the absence of a value. Moreover, its inclusion in interpolation segments leads to the dreaded "nil" in output that is often fed to UI elements. Even barring that, interpolating a non-nil optional value yields "Optional("value")", a result that is not useful even in logged output.

Given that the Optional type is never fit for display to the end user, and can often be a surprising find in the console, we propose that requesting an Optional's debug description be an explicit act. This proposal now requires a warning when using an expression of Optional type within a string interpolation segment.

Proposed solution

The user will be warned after attempting to use an expression with type Optional<T> in a string interpolation segment. They will then be offered a fixit suggesting they explicitly request the debugDescription of the Optional value instead.

Detailed design

Semantic analysis currently does not do much but guarantee the well-formedness of expressions in interpolation segments. These are then fed directly to String.init(stringInterpolationSegment:) and are run through the runtime reflection system to generate a description. Semantic analysis will be tweaked to inspect the result of solving an interpolation segment for an Optional and will offer a fixit in that case.

Impact on existing code

As this is a warning, code written before this proposal will continue to compile and run with the same semantics as before. Authors of code that makes use of this unsafe pattern will be offered a migration path to the safer, more explicit form.

Alternatives considered

A fixit that suggests a default value be inserted would be entirely appropriate (following the style of the fixit introduced in SE-0140).

Forbidding this pattern by hard error would make this proposal a breaking change that is out of scope for this stage of Swift's development.

A fixit that introduces a force-unwrapping would technically work as well, however it would be fixing a dangerous operation with yet another dangerous operation.

Sent from my iPad
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Robert Widmann) #12

I assume you meant that as a reply to me?

The problem is twofold:

1. Printing the value without adornment, or "nil" for nil, is a very common thing to want to do and we shouldn't have to write code like `\(x.map(String.init(describing:)) ?? "nil")` to accomplish it.

My point is before you were unable to do this without the ‘uglyness’ presented here anyway [you would have gotten “Optional(“value”)”], so I don’t see the point of raising this concern. If you want the old behavior, just ask for it with an explicit cast or `.debugDescription`.

2. Due to the changes made to IUOs, if you use a IUO in a string interpolation, previously it would print as desired (either the value or the string `"nil"`) but now it prints as Optional (e.g. with the `"Optional(…)"` wrapper).

IUOs are not in the scope for this proposal, but I get your point.

···

On Oct 3, 2016, at 8:49 PM, Kevin Ballard via swift-evolution <swift-evolution@swift.org> wrote:

-Kevin

On Mon, Oct 3, 2016, at 05:43 PM, Robert Widmann via swift-evolution wrote:

Under our proposal you can return to the old semantics of printing nil with an explicit optional cast - one which we will offer to insert for you.

Otherwise if you actually intend for a default value that value would have type Int, not String. Under the current regime if you want to print something custom the for nil the way you've got it now you're going to have to go through the reflecting initializer anyway so I don't see a problem here.

~Robert Widmann

2016/10/03 19:25、Charlie Monroe via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> のメッセージ:

I've already suggested this quite some time back and was told that this doesn't need to go through evolution. It's filed here: https://bugs.swift.org/browse/SR-1882

Unfortunately, I haven't had time to look into it myself and I'm unlikely to have the time anytime soon...

On Oct 3, 2016, at 7:52 PM, Harlan Haskins via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a proposal to mitigate something that's burned us all since Swift 1. We'd love some feedback!

It's available here: https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments

Proposal: SE-NNNN <https://gist.github.com/harlanhaskins/NNNN-filename.md>
Authors: Harlan Haskins <https://github.com/harlanhaskins>, Julio Carrettoni <https://github.com/Julioacarrettoni>, Robert Widmann <https://github.com/CodaFi>
Review Manager: TBD
Status: Awaiting revie
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#introduction>Introduction

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Swift-evolution thread: Discussion thread topic for that proposal <https://lists.swift.org/pipermail/swift-evolution/>
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#motivation>Motivation

The Swift Programming Language defines string interpolation segments as "a way to construct a new String value from a mix of constants, variables, literals, and expressions". There is one type that runs counter to this definition: Optional. The .none case in particular is used to indicate the absence of a value. Moreover, its inclusion in interpolation segments leads to the dreaded "nil" in output that is often fed to UI elements. Even barring that, interpolating a non-nil optional value yields "Optional("value")", a result that is not useful even in logged output.

Given that the Optional type is never fit for display to the end user, and can often be a surprising find in the console, we propose that requesting an Optional's debug description be an explicit act. This proposal now requires a warning when using an expression of Optional type within a string interpolation segment.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#proposed-solution>Proposed solution

The user will be warned after attempting to use an expression with type Optional<T> in a string interpolation segment. They will then be offered a fixit suggesting they explicitly request the debugDescription of the Optional value instead.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#detailed-design>Detailed design

Semantic analysis currently does not do much but guarantee the well-formedness of expressions in interpolation segments. These are then fed directly to String.init(stringInterpolationSegment:) and are run through the runtime reflection system to generate a description. Semantic analysis will be tweaked to inspect the result of solving an interpolation segment for an Optional and will offer a fixit in that case.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#impact-on-existing-code>Impact on existing code

As this is a warning, code written before this proposal will continue to compile and run with the same semantics as before. Authors of code that makes use of this unsafe pattern will be offered a migration path to the safer, more explicit form.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#alternatives-considered>Alternatives considered

A fixit that suggests a default value be inserted would be entirely appropriate (following the style of the fixit introduced in SE-0140 <https://github.com/apple/swift-evolution/blob/master/proposals/0140-bridge-optional-to-nsnull.md>).

Forbidding this pattern by hard error would make this proposal a breaking change that is out of scope for this stage of Swift's development.

A fixit that introduces a force-unwrapping would technically work as well, however it would be fixing a dangerous operation with yet another dangerous operation.

Sent from my iPad
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Robert Widmann) #13

I assume you meant that as a reply to me?

The problem is twofold:

1. Printing the value without adornment, or "nil" for nil, is a very common thing to want to do and we shouldn't have to write code like `\(x.map(String.init(describing:)) ?? "nil")` to accomplish it.

My point is before you were unable to do this without the ‘uglyness’ presented here anyway [you would have gotten “Optional(“value”)”], so I don’t see the point of raising this concern. If you want the old behavior, just ask for it with an explicit cast or `.debugDescription`.

This proposal was done because the current behavior of Optionals in string interpolation isn't very useful for most people. You're proposing banning it outright (with an escape hatch to recover the current behavior). I'm saying that, since it isn't very useful for most people, instead of banning it we could make it useful.

Then Optional needs to have a stable and useful `.description`, but I don’t think it’s appropriate to have users rely on the output of `debugDescription` much less use it in interpolated strings as it is now. That’s why we wrote this proposal. We are changing no behavior, your programs will still compile under this proposal, they will still execute with the same semantics as before, you will just get a warning that you cannot and should not depend on the debug representation of a type that specifically has a case for “no value here”. If you want to silence that warning you’re gonna have to jump through some hoops - hoops that we’ll show you with fixits.

···

On Oct 3, 2016, at 9:54 PM, Kevin Ballard <kevin@sb.org> wrote:
On Mon, Oct 3, 2016, at 06:49 PM, Robert Widmann wrote:

On Oct 3, 2016, at 8:49 PM, Kevin Ballard via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

-Kevin

2. Due to the changes made to IUOs, if you use a IUO in a string interpolation, previously it would print as desired (either the value or the string `"nil"`) but now it prints as Optional (e.g. with the `"Optional(…)"` wrapper).

IUOs are not in the scope for this proposal, but I get your point.

-Kevin

On Mon, Oct 3, 2016, at 05:43 PM, Robert Widmann via swift-evolution wrote:

Under our proposal you can return to the old semantics of printing nil with an explicit optional cast - one which we will offer to insert for you.

Otherwise if you actually intend for a default value that value would have type Int, not String. Under the current regime if you want to print something custom the for nil the way you've got it now you're going to have to go through the reflecting initializer anyway so I don't see a problem here.

~Robert Widmann

2016/10/03 19:25、Charlie Monroe via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> のメッセージ:

I've already suggested this quite some time back and was told that this doesn't need to go through evolution. It's filed here: https://bugs.swift.org/browse/SR-1882

Unfortunately, I haven't had time to look into it myself and I'm unlikely to have the time anytime soon...

On Oct 3, 2016, at 7:52 PM, Harlan Haskins via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a proposal to mitigate something that's burned us all since Swift 1. We'd love some feedback!

It's available here: https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments

Proposal: SE-NNNN <https://gist.github.com/harlanhaskins/NNNN-filename.md>
Authors: Harlan Haskins <https://github.com/harlanhaskins>, Julio Carrettoni <https://github.com/Julioacarrettoni>, Robert Widmann <https://github.com/CodaFi>
Review Manager: TBD
Status: Awaiting revie
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#introduction>Introduction

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Swift-evolution thread: Discussion thread topic for that proposal <https://lists.swift.org/pipermail/swift-evolution/>
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#motivation>Motivation

The Swift Programming Language defines string interpolation segments as "a way to construct a new String value from a mix of constants, variables, literals, and expressions". There is one type that runs counter to this definition: Optional. The .none case in particular is used to indicate the absence of a value. Moreover, its inclusion in interpolation segments leads to the dreaded "nil" in output that is often fed to UI elements. Even barring that, interpolating a non-nil optional value yields "Optional("value")", a result that is not useful even in logged output.

Given that the Optional type is never fit for display to the end user, and can often be a surprising find in the console, we propose that requesting an Optional's debug description be an explicit act. This proposal now requires a warning when using an expression of Optional type within a string interpolation segment.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#proposed-solution>Proposed solution

The user will be warned after attempting to use an expression with type Optional<T> in a string interpolation segment. They will then be offered a fixit suggesting they explicitly request the debugDescription of the Optional value instead.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#detailed-design>Detailed design

Semantic analysis currently does not do much but guarantee the well-formedness of expressions in interpolation segments. These are then fed directly to String.init(stringInterpolationSegment:) and are run through the runtime reflection system to generate a description. Semantic analysis will be tweaked to inspect the result of solving an interpolation segment for an Optional and will offer a fixit in that case.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#impact-on-existing-code>Impact on existing code

As this is a warning, code written before this proposal will continue to compile and run with the same semantics as before. Authors of code that makes use of this unsafe pattern will be offered a migration path to the safer, more explicit form.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#alternatives-considered>Alternatives considered

A fixit that suggests a default value be inserted would be entirely appropriate (following the style of the fixit introduced in SE-0140 <https://github.com/apple/swift-evolution/blob/master/proposals/0140-bridge-optional-to-nsnull.md>).

Forbidding this pattern by hard error would make this proposal a breaking change that is out of scope for this stage of Swift's development.

A fixit that introduces a force-unwrapping would technically work as well, however it would be fixing a dangerous operation with yet another dangerous operation.

Sent from my iPad
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Robert Widmann) #14

Forgive me for mixing terminology from before stating “If you want the old behavior” and the like. What I meant is “If you want to silence the warning”. I should point out that it is just that: a warning. We specifically mention that we didn’t spring for a hard error because that would make this a source-breaking proposal and we realize that it is useful to be able to quickly print an optional to test something. But at the end of the day you should think about the representation of data flowing through your program and be explicit about whether you want the debug interpretation of an optional value or whether you intended - as we believe is true of the majority of cases - to provide a default non-optional value.

···

On Oct 3, 2016, at 9:54 PM, Kevin Ballard <kevin@sb.org> wrote:

On Mon, Oct 3, 2016, at 06:49 PM, Robert Widmann wrote:

On Oct 3, 2016, at 8:49 PM, Kevin Ballard via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I assume you meant that as a reply to me?

The problem is twofold:

1. Printing the value without adornment, or "nil" for nil, is a very common thing to want to do and we shouldn't have to write code like `\(x.map(String.init(describing:)) ?? "nil")` to accomplish it.

My point is before you were unable to do this without the ‘uglyness’ presented here anyway [you would have gotten “Optional(“value”)”], so I don’t see the point of raising this concern. If you want the old behavior, just ask for it with an explicit cast or `.debugDescription`.

This proposal was done because the current behavior of Optionals in string interpolation isn't very useful for most people. You're proposing banning it outright (with an escape hatch to recover the current behavior). I'm saying that, since it isn't very useful for most people, instead of banning it we could make it useful.

-Kevin

2. Due to the changes made to IUOs, if you use a IUO in a string interpolation, previously it would print as desired (either the value or the string `"nil"`) but now it prints as Optional (e.g. with the `"Optional(…)"` wrapper).

IUOs are not in the scope for this proposal, but I get your point.

-Kevin

On Mon, Oct 3, 2016, at 05:43 PM, Robert Widmann via swift-evolution wrote:

Under our proposal you can return to the old semantics of printing nil with an explicit optional cast - one which we will offer to insert for you.

Otherwise if you actually intend for a default value that value would have type Int, not String. Under the current regime if you want to print something custom the for nil the way you've got it now you're going to have to go through the reflecting initializer anyway so I don't see a problem here.

~Robert Widmann

2016/10/03 19:25、Charlie Monroe via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> のメッセージ:

I've already suggested this quite some time back and was told that this doesn't need to go through evolution. It's filed here: https://bugs.swift.org/browse/SR-1882

Unfortunately, I haven't had time to look into it myself and I'm unlikely to have the time anytime soon...

On Oct 3, 2016, at 7:52 PM, Harlan Haskins via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a proposal to mitigate something that's burned us all since Swift 1. We'd love some feedback!

It's available here: https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments

Proposal: SE-NNNN <https://gist.github.com/harlanhaskins/NNNN-filename.md>
Authors: Harlan Haskins <https://github.com/harlanhaskins>, Julio Carrettoni <https://github.com/Julioacarrettoni>, Robert Widmann <https://github.com/CodaFi>
Review Manager: TBD
Status: Awaiting revie
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#introduction>Introduction

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Swift-evolution thread: Discussion thread topic for that proposal <https://lists.swift.org/pipermail/swift-evolution/>
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#motivation>Motivation

The Swift Programming Language defines string interpolation segments as "a way to construct a new String value from a mix of constants, variables, literals, and expressions". There is one type that runs counter to this definition: Optional. The .none case in particular is used to indicate the absence of a value. Moreover, its inclusion in interpolation segments leads to the dreaded "nil" in output that is often fed to UI elements. Even barring that, interpolating a non-nil optional value yields "Optional("value")", a result that is not useful even in logged output.

Given that the Optional type is never fit for display to the end user, and can often be a surprising find in the console, we propose that requesting an Optional's debug description be an explicit act. This proposal now requires a warning when using an expression of Optional type within a string interpolation segment.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#proposed-solution>Proposed solution

The user will be warned after attempting to use an expression with type Optional<T> in a string interpolation segment. They will then be offered a fixit suggesting they explicitly request the debugDescription of the Optional value instead.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#detailed-design>Detailed design

Semantic analysis currently does not do much but guarantee the well-formedness of expressions in interpolation segments. These are then fed directly to String.init(stringInterpolationSegment:) and are run through the runtime reflection system to generate a description. Semantic analysis will be tweaked to inspect the result of solving an interpolation segment for an Optional and will offer a fixit in that case.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#impact-on-existing-code>Impact on existing code

As this is a warning, code written before this proposal will continue to compile and run with the same semantics as before. Authors of code that makes use of this unsafe pattern will be offered a migration path to the safer, more explicit form.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#alternatives-considered>Alternatives considered

A fixit that suggests a default value be inserted would be entirely appropriate (following the style of the fixit introduced in SE-0140 <https://github.com/apple/swift-evolution/blob/master/proposals/0140-bridge-optional-to-nsnull.md>).

Forbidding this pattern by hard error would make this proposal a breaking change that is out of scope for this stage of Swift's development.

A fixit that introduces a force-unwrapping would technically work as well, however it would be fixing a dangerous operation with yet another dangerous operation.

Sent from my iPad
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Charlie Monroe) #15

I assume you meant that as a reply to me?

The problem is twofold:

1. Printing the value without adornment, or "nil" for nil, is a very common thing to want to do and we shouldn't have to write code like `\(x.map(String.init(describing:)) ?? "nil")` to accomplish it.

My point is before you were unable to do this without the ‘uglyness’ presented here anyway [you would have gotten “Optional(“value”)”], so I don’t see the point of raising this concern. If you want the old behavior, just ask for it with an explicit cast or `.debugDescription`.

This proposal was done because the current behavior of Optionals in string interpolation isn't very useful for most people. You're proposing banning it outright (with an escape hatch to recover the current behavior). I'm saying that, since it isn't very useful for most people, instead of banning it we could make it useful.

Then Optional needs to have a stable and useful `.description`, but I don’t think it’s appropriate to have users rely on the output of `debugDescription` much less use it in interpolated strings as it is now. That’s why we wrote this proposal. We are changing no behavior, your programs will still compile under this proposal, they will still execute with the same semantics as before, you will just get a warning that you cannot and should not depend on the debug representation of a type that specifically has a case for “no value here”. If you want to silence that warning you’re gonna have to jump through some hoops - hoops that we’ll show you with fixits.

There were these concerns:

- the documentation explicitly discourages people to call description or debugDescription from within the code. So my original suggestion to make the fixit simply call debugDescription was met with resistance since this is discouraged. I am not sure about the reasoning for this though.

- some people did find the Optional(value) wrap useful and changing it could be viewed on as breaking change, though cases where the user may be testing a string for Optional seems rare at best. But again, there were voices that were loudly against.

- suggestion by Chris Lattner was to silence the warning either by:
  - wrapping the expression in extra parentheses
  - adding ?? and default value

Personally, I do not like this suggestion since it makes the code readability low due to the fact that the expression is within a string and thus formatting options that would help you improve readability are limited.

I've suggested adding two methods to Optional<T>:

- func descriptionWithDefaultValue(_ value: String = "nil") which while more descriptive isn't discouraged from being called directly and allows you to specify nil value (I have use cases for empty string, etc.)

- var detailedDescription: String - simply returns current implementation of debugDescription

My extension of Optional<T>:

https://github.com/charlieMonroe/XUCore/blob/master/XUCore/additions/OptionalAdditions.swift

Original proposal:

https://gist.github.com/charlieMonroe/82e1519dd2b57029f69bc7abe99d7385

···

On Oct 4, 2016, at 3:57 AM, Robert Widmann via swift-evolution <swift-evolution@swift.org> wrote:

On Oct 3, 2016, at 9:54 PM, Kevin Ballard <kevin@sb.org <mailto:kevin@sb.org>> wrote:
On Mon, Oct 3, 2016, at 06:49 PM, Robert Widmann wrote:

On Oct 3, 2016, at 8:49 PM, Kevin Ballard via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

-Kevin

2. Due to the changes made to IUOs, if you use a IUO in a string interpolation, previously it would print as desired (either the value or the string `"nil"`) but now it prints as Optional (e.g. with the `"Optional(…)"` wrapper).

IUOs are not in the scope for this proposal, but I get your point.

-Kevin

On Mon, Oct 3, 2016, at 05:43 PM, Robert Widmann via swift-evolution wrote:

Under our proposal you can return to the old semantics of printing nil with an explicit optional cast - one which we will offer to insert for you.

Otherwise if you actually intend for a default value that value would have type Int, not String. Under the current regime if you want to print something custom the for nil the way you've got it now you're going to have to go through the reflecting initializer anyway so I don't see a problem here.

~Robert Widmann

2016/10/03 19:25、Charlie Monroe via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> のメッセージ:

I've already suggested this quite some time back and was told that this doesn't need to go through evolution. It's filed here: https://bugs.swift.org/browse/SR-1882

Unfortunately, I haven't had time to look into it myself and I'm unlikely to have the time anytime soon...

On Oct 3, 2016, at 7:52 PM, Harlan Haskins via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a proposal to mitigate something that's burned us all since Swift 1. We'd love some feedback!

It's available here: https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments

Proposal: SE-NNNN <https://gist.github.com/harlanhaskins/NNNN-filename.md>
Authors: Harlan Haskins <https://github.com/harlanhaskins>, Julio Carrettoni <https://github.com/Julioacarrettoni>, Robert Widmann <https://github.com/CodaFi>
Review Manager: TBD
Status: Awaiting revie
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#introduction>Introduction

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Swift-evolution thread: Discussion thread topic for that proposal <https://lists.swift.org/pipermail/swift-evolution/>
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#motivation>Motivation

The Swift Programming Language defines string interpolation segments as "a way to construct a new String value from a mix of constants, variables, literals, and expressions". There is one type that runs counter to this definition: Optional. The .none case in particular is used to indicate the absence of a value. Moreover, its inclusion in interpolation segments leads to the dreaded "nil" in output that is often fed to UI elements. Even barring that, interpolating a non-nil optional value yields "Optional("value")", a result that is not useful even in logged output.

Given that the Optional type is never fit for display to the end user, and can often be a surprising find in the console, we propose that requesting an Optional's debug description be an explicit act. This proposal now requires a warning when using an expression of Optional type within a string interpolation segment.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#proposed-solution>Proposed solution

The user will be warned after attempting to use an expression with type Optional<T> in a string interpolation segment. They will then be offered a fixit suggesting they explicitly request the debugDescription of the Optional value instead.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#detailed-design>Detailed design

Semantic analysis currently does not do much but guarantee the well-formedness of expressions in interpolation segments. These are then fed directly to String.init(stringInterpolationSegment:) and are run through the runtime reflection system to generate a description. Semantic analysis will be tweaked to inspect the result of solving an interpolation segment for an Optional and will offer a fixit in that case.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#impact-on-existing-code>Impact on existing code

As this is a warning, code written before this proposal will continue to compile and run with the same semantics as before. Authors of code that makes use of this unsafe pattern will be offered a migration path to the safer, more explicit form.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#alternatives-considered>Alternatives considered

A fixit that suggests a default value be inserted would be entirely appropriate (following the style of the fixit introduced in SE-0140 <https://github.com/apple/swift-evolution/blob/master/proposals/0140-bridge-optional-to-nsnull.md>).

Forbidding this pattern by hard error would make this proposal a breaking change that is out of scope for this stage of Swift's development.

A fixit that introduces a force-unwrapping would technically work as well, however it would be fixing a dangerous operation with yet another dangerous operation.

Sent from my iPad
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Jeremy Pereira) #16

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Is there any way we could instead allow Optionals but just print them the way we print ImplicitlyUnwrappedOptionals? That's almost always how I want my Optionals to work when interpolating. To be specific, this means for .some(x) we just print x, and for .none we print "nil”.

On the other hand, when I interpolate an optional, I want it to be obvious that it is an Optional. If I didn’t want Optional(foo) in the string, I would unwrap it first.

I also disagree with the proposal that the behaviour is surprising. What else would you expect?

Having said that, I have no objection to the proposed warning.

···

On 3 Oct 2016, at 22:41, Kevin Ballard via swift-evolution <swift-evolution@swift.org> wrote:
On Mon, Oct 3, 2016, at 10:52 AM, Harlan Haskins via swift-evolution wrote:

-Kevin
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Joe Groff) #17

Because the initializer here doesn’t take Any, it takes <T>.

I think there's a case to be made to generalize the 'Any' warning to Optional implicitly being deduced as a type variable binding in any unconstrained context. What exactly constitutes 'implicit' and 'unconstrained' is up for debate, though, and probably needs some experimentation to figure out what feels good. For instance, explicitly constructing an optional is a signal the optionality intentional. Potentially, having multiple Optional parameters binding the same type variable also increases the likelihood it's intended, for example:

func foo<T>(x: T, y: T) {}

var x: Int? = 1
var y: Int = 2
foo(x, y) // One Optional isn't unwrapped, forcing the other to promote. Maybe a mistake?
var z: Int? = 3
foo(x, z) // Two T parameters are Optional. Probably intentional?

Regardless of whether there's a more general principle we can base a warning on, string interpolation and String(describing:) are common enough pitfalls that they may just deserve special case treatment.

-Joe

···

On Oct 3, 2016, at 11:02 AM, Robert Widmann <devteam.codafi@gmail.com> wrote:

~Robert Widmann

On Oct 3, 2016, at 2:00 PM, Harlan Haskins via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Unfortunately, Optional-to-Any does not currently hit this case because IIRC it doesn't promote to Any in an interpolation segment. I tested this with a ToT build yesterday.

- Harlan

On Oct 3, 2016, at 1:57 PM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

We now emit a warning whenever an optional is used as an Any. I disagree that this should be an error, but it seems reasonable to warn (if we don't already thanks to the 'Any' warning).

-Joe

On Oct 3, 2016, at 10:52 AM, Harlan Haskins via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a proposal to mitigate something that's burned us all since Swift 1. We'd love some feedback!

It's available here: https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments

Proposal: SE-NNNN <https://gist.github.com/harlanhaskins/NNNN-filename.md>
Authors: Harlan Haskins <https://github.com/harlanhaskins>, Julio Carrettoni <https://github.com/Julioacarrettoni>, Robert Widmann <https://github.com/CodaFi>
Review Manager: TBD
Status: Awaiting revie
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#introduction>Introduction

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Swift-evolution thread: Discussion thread topic for that proposal <https://lists.swift.org/pipermail/swift-evolution/>
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#motivation>Motivation

The Swift Programming Language defines string interpolation segments as "a way to construct a new String value from a mix of constants, variables, literals, and expressions". There is one type that runs counter to this definition: Optional. The .none case in particular is used to indicate the absence of a value. Moreover, its inclusion in interpolation segments leads to the dreaded "nil" in output that is often fed to UI elements. Even barring that, interpolating a non-nil optional value yields "Optional("value")", a result that is not useful even in logged output.

Given that the Optional type is never fit for display to the end user, and can often be a surprising find in the console, we propose that requesting an Optional's debug description be an explicit act. This proposal now requires a warning when using an expression of Optional type within a string interpolation segment.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#proposed-solution>Proposed solution

The user will be warned after attempting to use an expression with type Optional<T> in a string interpolation segment. They will then be offered a fixit suggesting they explicitly request the debugDescription of the Optional value instead.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#detailed-design>Detailed design

Semantic analysis currently does not do much but guarantee the well-formedness of expressions in interpolation segments. These are then fed directly to String.init(stringInterpolationSegment:) and are run through the runtime reflection system to generate a description. Semantic analysis will be tweaked to inspect the result of solving an interpolation segment for an Optional and will offer a fixit in that case.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#impact-on-existing-code>Impact on existing code

As this is a warning, code written before this proposal will continue to compile and run with the same semantics as before. Authors of code that makes use of this unsafe pattern will be offered a migration path to the safer, more explicit form.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#alternatives-considered>Alternatives considered

A fixit that suggests a default value be inserted would be entirely appropriate (following the style of the fixit introduced in SE-0140 <https://github.com/apple/swift-evolution/blob/master/proposals/0140-bridge-optional-to-nsnull.md>).

Forbidding this pattern by hard error would make this proposal a breaking change that is out of scope for this stage of Swift's development.

A fixit that introduces a force-unwrapping would technically work as well, however it would be fixing a dangerous operation with yet another dangerous operation.

Sent from my iPad
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Mark Lacey) #18

Because the initializer here doesn’t take Any, it takes <T>.

I think there's a case to be made to generalize the 'Any' warning to Optional implicitly being deduced as a type variable binding in any unconstrained context. What exactly constitutes 'implicit' and 'unconstrained' is up for debate, though, and probably needs some experimentation to figure out what feels good. For instance, explicitly constructing an optional is a signal the optionality intentional. Potentially, having multiple Optional parameters binding the same type variable also increases the likelihood it's intended, for example:

func foo<T>(x: T, y: T) {}

var x: Int? = 1
var y: Int = 2
foo(x, y) // One Optional isn't unwrapped, forcing the other to promote. Maybe a mistake?
var z: Int? = 3
foo(x, z) // Two T parameters are Optional. Probably intentional?

Regardless of whether there's a more general principle we can base a warning on, string interpolation and String(describing:) are common enough pitfalls that they may just deserve special case treatment.

I think string interpolation could be handled pretty easily with a warning by extending the existing warning for Any. We just need to look at interpolation expressions and if any of the segments are optional-typed emit a warning unless they are explicitly casted to the optional type. The fixit can suggest explicit casting or using the debugDescription.

I’m not sure we really need an evolution proposal for that.

As for the more general topic of trickiness around optional injection into unconstrained generics: Yes, we should review that at some point as well. I recall seeing at least one concrete complaint about surprising behavior resulting from doing this in generic functions, but I cannot find the bug at the moment.

Mark

···

On Oct 3, 2016, at 11:26 AM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

On Oct 3, 2016, at 11:02 AM, Robert Widmann <devteam.codafi@gmail.com <mailto:devteam.codafi@gmail.com>> wrote:

-Joe

~Robert Widmann

On Oct 3, 2016, at 2:00 PM, Harlan Haskins via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Unfortunately, Optional-to-Any does not currently hit this case because IIRC it doesn't promote to Any in an interpolation segment. I tested this with a ToT build yesterday.

- Harlan

On Oct 3, 2016, at 1:57 PM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

We now emit a warning whenever an optional is used as an Any. I disagree that this should be an error, but it seems reasonable to warn (if we don't already thanks to the 'Any' warning).

-Joe

On Oct 3, 2016, at 10:52 AM, Harlan Haskins via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a proposal to mitigate something that's burned us all since Swift 1. We'd love some feedback!

It's available here: https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments

Proposal: SE-NNNN <https://gist.github.com/harlanhaskins/NNNN-filename.md>
Authors: Harlan Haskins <https://github.com/harlanhaskins>, Julio Carrettoni <https://github.com/Julioacarrettoni>, Robert Widmann <https://github.com/CodaFi>
Review Manager: TBD
Status: Awaiting revie
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#introduction>Introduction

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Swift-evolution thread: Discussion thread topic for that proposal <https://lists.swift.org/pipermail/swift-evolution/>
<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#motivation>Motivation

The Swift Programming Language defines string interpolation segments as "a way to construct a new String value from a mix of constants, variables, literals, and expressions". There is one type that runs counter to this definition: Optional. The .none case in particular is used to indicate the absence of a value. Moreover, its inclusion in interpolation segments leads to the dreaded "nil" in output that is often fed to UI elements. Even barring that, interpolating a non-nil optional value yields "Optional("value")", a result that is not useful even in logged output.

Given that the Optional type is never fit for display to the end user, and can often be a surprising find in the console, we propose that requesting an Optional's debug description be an explicit act. This proposal now requires a warning when using an expression of Optional type within a string interpolation segment.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#proposed-solution>Proposed solution

The user will be warned after attempting to use an expression with type Optional<T> in a string interpolation segment. They will then be offered a fixit suggesting they explicitly request the debugDescription of the Optional value instead.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#detailed-design>Detailed design

Semantic analysis currently does not do much but guarantee the well-formedness of expressions in interpolation segments. These are then fed directly to String.init(stringInterpolationSegment:) and are run through the runtime reflection system to generate a description. Semantic analysis will be tweaked to inspect the result of solving an interpolation segment for an Optional and will offer a fixit in that case.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#impact-on-existing-code>Impact on existing code

As this is a warning, code written before this proposal will continue to compile and run with the same semantics as before. Authors of code that makes use of this unsafe pattern will be offered a migration path to the safer, more explicit form.

<https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#alternatives-considered>Alternatives considered

A fixit that suggests a default value be inserted would be entirely appropriate (following the style of the fixit introduced in SE-0140 <https://github.com/apple/swift-evolution/blob/master/proposals/0140-bridge-optional-to-nsnull.md>).

Forbidding this pattern by hard error would make this proposal a breaking change that is out of scope for this stage of Swift's development.

A fixit that introduces a force-unwrapping would technically work as well, however it would be fixing a dangerous operation with yet another dangerous operation.

Sent from my iPad
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Lily Ballard) #19

But you can't write that, unless you're dealing specifically with an
Optional<String>. If you try you'll get an error:

unnamed.swift:2:19: error: binary operator '??' cannot be applied to
operands of type 'Int?' and 'String'
    print("x: \(x ?? "nil")")
                ~ ^ ~~~~~
unnamed.swift:2:19: note: overloads for '??' exist with these partially
matching parameter lists: (T?, @autoclosure () throws -> T), (T?,
@autoclosure () thro
ws -> T?)
    print("x: \(x ?? "nil")")
                  ^
This leads to writing code like "… \(x.map(String.init(describing:)) ??
"nil")" which is pretty gross.

-Kevin

···

On Mon, Oct 3, 2016, at 03:18 PM, Jordan Rose wrote:

On Oct 3, 2016, at 14:41, Kevin Ballard via swift-evolution <swift- >> evolution@swift.org> wrote:

On Mon, Oct 3, 2016, at 10:52 AM, Harlan Haskins via swift- >> evolution wrote:

Swift developers frequently use string interpolation as a
convenient, concise syntax for interweaving variable values with
strings. The interpolation machinery, however, has surprising
behavior in one specific case: Optional<T>. If a user puts an
optional value into a string interpolation segment, it will insert
either "Optional("value")" or "nil" in the resulting string. Neither
of these is particularly desirable, so we propose a warning and fix-
it to surface solutions to these potential mistakes.

Is there any way we could instead allow Optionals but just print
them the way we print ImplicitlyUnwrappedOptionals? That's almost
always how I want my Optionals to work when interpolating. To be
specific, this means for .some(x) we just print x, and for .none we
print "nil".

We had this at one point, but we took it out because people would
forget to test the nil case. I think `?? ""` or `?? nil` really is the
best answer here.


(Robert Widmann) #20

Definitely right about that, the implementation <https://github.com/CodaFi/swift/commit/43a582ef0fb108369f3df955f617b77b71cbd45e#diff-9124ea1eb6021a3c7323d7a07fd85c1eR2409> took all of 10 minutes after extending the OptionalToAnyCoercionWalker. If you’ve got any comments, please let me know there.

~Robert Widmann

···

On Oct 3, 2016, at 4:06 PM, Mark Lacey <mark.lacey@apple.com> wrote:

On Oct 3, 2016, at 11:26 AM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

On Oct 3, 2016, at 11:02 AM, Robert Widmann <devteam.codafi@gmail.com> wrote:

Because the initializer here doesn’t take Any, it takes <T>.

I think there's a case to be made to generalize the 'Any' warning to Optional implicitly being deduced as a type variable binding in any unconstrained context. What exactly constitutes 'implicit' and 'unconstrained' is up for debate, though, and probably needs some experimentation to figure out what feels good. For instance, explicitly constructing an optional is a signal the optionality intentional. Potentially, having multiple Optional parameters binding the same type variable also increases the likelihood it's intended, for example:

func foo<T>(x: T, y: T) {}

var x: Int? = 1
var y: Int = 2
foo(x, y) // One Optional isn't unwrapped, forcing the other to promote. Maybe a mistake?
var z: Int? = 3
foo(x, z) // Two T parameters are Optional. Probably intentional?

Regardless of whether there's a more general principle we can base a warning on, string interpolation and String(describing:) are common enough pitfalls that they may just deserve special case treatment.

I think string interpolation could be handled pretty easily with a warning by extending the existing warning for Any. We just need to look at interpolation expressions and if any of the segments are optional-typed emit a warning unless they are explicitly casted to the optional type. The fixit can suggest explicit casting or using the debugDescription.

I’m not sure we really need an evolution proposal for that.

As for the more general topic of trickiness around optional injection into unconstrained generics: Yes, we should review that at some point as well. I recall seeing at least one concrete complaint about surprising behavior resulting from doing this in generic functions, but I cannot find the bug at the moment.

Mark

-Joe

~Robert Widmann

On Oct 3, 2016, at 2:00 PM, Harlan Haskins via swift-evolution <swift-evolution@swift.org> wrote:

Unfortunately, Optional-to-Any does not currently hit this case because IIRC it doesn't promote to Any in an interpolation segment. I tested this with a ToT build yesterday.

- Harlan

On Oct 3, 2016, at 1:57 PM, Joe Groff <jgroff@apple.com> wrote:

We now emit a warning whenever an optional is used as an Any. I disagree that this should be an error, but it seems reasonable to warn (if we don't already thanks to the 'Any' warning).

-Joe

On Oct 3, 2016, at 10:52 AM, Harlan Haskins via swift-evolution <swift-evolution@swift.org> wrote:

Hey all,

Julio Carrettoni, Robert Widmann, and I have been working on a proposal to mitigate something that's burned us all since Swift 1. We'd love some feedback!

It's available here: https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd

I've posted the current draft below.

Thanks,
Harlan Haskins

Disallow Optionals in String Interpolation Segments

  • Proposal: SE-NNNN
  • Authors: Harlan Haskins, Julio Carrettoni, Robert Widmann
  • Review Manager: TBD
  • Status: Awaiting revie
Introduction

Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: Optional<T>. If a user puts an optional value into a string interpolation segment, it will insert either "Optional("value")" or "nil" in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.

Swift-evolution thread: Discussion thread topic for that proposal

Motivation

The Swift Programming Language defines string interpolation segments as "a way to construct a new String value from a mix of constants, variables, literals, and expressions". There is one type that runs counter to this definition: Optional. The .none case in particular is used to indicate the absence of a value. Moreover, its inclusion in interpolation segments leads to the dreaded "nil" in output that is often fed to UI elements. Even barring that, interpolating a non-nil optional value yields "Optional("value")", a result that is not useful even in logged output.

Given that the Optional type is never fit for display to the end user, and can often be a surprising find in the console, we propose that requesting an Optional's debug description be an explicit act. This proposal now requires a warning when using an expression of Optional type within a string interpolation segment.

Proposed solution

The user will be warned after attempting to use an expression with type Optional<T> in a string interpolation segment. They will then be offered a fixit suggesting they explicitly request the debugDescription of the Optional value instead.

Detailed design

Semantic analysis currently does not do much but guarantee the well-formedness of expressions in interpolation segments. These are then fed directly to String.init(stringInterpolationSegment:) and are run through the runtime reflection system to generate a description. Semantic analysis will be tweaked to inspect the result of solving an interpolation segment for an Optional and will offer a fixit in that case.

Impact on existing code

As this is a warning, code written before this proposal will continue to compile and run with the same semantics as before. Authors of code that makes use of this unsafe pattern will be offered a migration path to the safer, more explicit form.

Alternatives considered

  • A fixit that suggests a default value be inserted would be entirely appropriate (following the style of the fixit introduced in SE-0140).

  • Forbidding this pattern by hard error would make this proposal a breaking change that is out of scope for this stage of Swift's development.

  • A fixit that introduces a force-unwrapping would technically work as well, however it would be fixing a dangerous operation with yet another dangerous operation.

Sent from my iPad
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution