Skip to content

[4.2] [Type checker] Improve diagnostics when an optional value is not unwrapped #17955

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

DougGregor
Copy link
Member

Explanation: The errors produced by the Swift compiler when a value of optional type is provided (but needs to be unwrapped) were poor, and led users to excessive force-unwraps (using '!') via a Fix-It. Improve the form of the diagnostics, taking the Fix-It off the primary diagnostic and instead providing two notes: one for either the coalescing operator (?? <#default value#>) or chaining operator (?.), depending on context, and one for the force-unwrap (!), which makes it clear that the program will abort execution if the underlying value is nil.
Scope: Affects ill-formed code that fails to properly unwrap optionals.
Risk: Effectively zero; this pull request is carefully factored to only improve on diagnostics, not touch the constraint solver core.
Testing: Compiler regression tests, including new tests.
Reviewer: @rudkx
SR / Radar: rdar://problem/42081852

…apped.

When we determine that an optional value needs to be unwrapped to make
an expression type check, use notes to provide several different
Fix-It options (with descriptions) rather than always pushing users
toward '!'. Specifically, the errors + Fix-Its now looks like this:

    error: value of optional type 'X?' must be unwrapped to a value of
        type 'X'
      f(x)
        ^
    note: coalesce using '??' to provide a default when the optional
        value contains 'nil'
      f(x)
        ^
          ?? <#default value#>
    note: force-unwrap using '!' to abort execution if the optional
        value contains 'nil'
      f(x)
         ^
         !

Fixes rdar://problem/42081852.

(cherry picked from commit 945c09b)
…ional base.

Improve diagnostics when referencing a member of an optional base, where the
Optional type does not have the member but the wrapped type does. Specifically,
suggest both the chaining ‘?’ and the force-unwrapping ‘!’ Fix-Its via explanatory
notes, e.g.:

  error: value of optional type '[Int]?' must be unwrapped to refer to member 'subscript' of wrapped base type '[Int]'
    return foo.array[0]
               ^
  note: chain the optional using '?' to access member 'subscript' only for non-'nil' base values
    return foo.array[0]
               ^
                    ?
  note: force-unwrap using '!' to abort execution if the optional value contains 'nil'
    return foo.array[0]
               ^
                    !

More of rdar://problem/42081852.

(cherry picked from commit 9ec3b00)
…mber access.

Introduce a new fix kind into the constraint solver to cover unwrapping the base
of a member access so we can refer to the a member of the unwrapped base.
Wire this fix kind to the just-added diagnostic that suggests either the
chaining ‘?’ or the force-unwrap ‘!’ via separate, descriptive Fix-Its.

Example:

error: value of optional type 'X?' must be unwrapped to refer to member 'f' of wrapped base type 'X'
  let _: Int = x.f()
               ^
note: chain the optional using '?' to access member 'f' only for non-'nil' base values
  let _: Int = x.f()
               ^
                ?
note: force-unwrap using '!' to abort execution if the optional value contains 'nil'
  let _: Int = x.f()
               ^
                !

Before this, we would sometimes get a Fix-It for just ‘?’ and sometimes get a Fix-It for the
coalescing ‘??’, neither of which is likely to be right.

More work on rdar://problem/42081852.

(cherry picked from commit e7eac0a)
…wraps more consistently.

Replace the last (and most obscure) use of the poor “use ‘?’ or ‘!’” diagnostic with the
new, more explanatory version that provides separate notes with Fix-Its for coalescing or
force-unwrapping the value.

Finishes rdar://problem/42081852.

(cherry picked from commit 5db1901)
@DougGregor DougGregor changed the title [Type checker] Improve diagnostics when an optional value is not unwrapped [4.2] [Type checker] Improve diagnostics when an optional value is not unwrapped Jul 15, 2018
@DougGregor
Copy link
Member Author

@swift-ci please test

@DougGregor
Copy link
Member Author

@swift-ci please nominate

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - f027bd5

@DougGregor
Copy link
Member Author

@swift-ci please test macOS

@AnnaZaks AnnaZaks merged commit aaf545a into swiftlang:swift-4.2-branch Jul 16, 2018
@DougGregor DougGregor deleted the optional-not-unwrapped-diags-4.2 branch July 16, 2018 16:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants