Skip to content

[Sema] [SR-4347] Improve inference of optional supertypes #8339

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

Merged
merged 5 commits into from
Apr 6, 2017
Merged

[Sema] [SR-4347] Improve inference of optional supertypes #8339

merged 5 commits into from
Apr 6, 2017

Conversation

tonisuter
Copy link
Contributor

If an array literal contains at least one element that is a nil literal and at least one other element that is of type T, the type checker will infer an array element type of Optional<T>:

let arr1 = [1, nil, 3]
print(type(of: arr1)) 		// Array<Optional<Int>>

struct S {}
let arr2 = [S(), nil]
print(type(of: arr2))		// Array<Optional<S>>

Similarly, there are other situations where the compiler can infer a common optional supertype:

let x = true ? 2 : nil
print(type(of: x))		// Optional<Int>

struct S {}
let y = false ? nil : S()
print(type(of: y))		// Optional<S>

However, this currently only works if T is a nominal type (and does not conform to ExpressibleByNilLiteral). If T is any other kind of type (e.g., a tuple type, a function type, a generic parameter, Any), the compiler will emit a type error (see discussion on the mailing list).

This pull request fixes this to allow inference of an optional supertype for any kind of type T.

Resolves SR-4347.

@slavapestov
Copy link
Contributor

@rudkx Want to take a look?

@tonisuter
Copy link
Contributor Author

@swift-ci Please smoke test

@rudkx
Copy link
Contributor

rudkx commented Mar 25, 2017

A couple comments:

  • The change looks good. The tests don't cover all the new types that you're allowing, though, so can you add tests for other non-nominal types that users can spell, e.g. metatypes?
  • For [1 as Int, 1.0, nil], I would expect to get [Any?], and would expect to reject this as the inferred type just like we do with [Any] today, but we don't seem to get [Any?] here - we get a message about the result being ambiguous without more context. Can you look into this if you have time?

@slavapestov
Copy link
Contributor

Another code path that is relevant in collection element type inference is in lib/AST/TypeJoinMeet.cpp. Does that need generalization too? @rudkx Do you know what the difference is between the code being changed in this PR, and the type join stuff?

@tonisuter
Copy link
Contributor Author

Thanks for your feedback! I've added additional test cases for metatypes, protocol composition types, etc. I also noticed that the existing test cases don't cover the case where T is a nominal type that conforms to ExpressibleByNilLiteral, so I added test cases for that as well. I will try to fix the other issue in the coming days.

BTW, why does it still say Some checks haven't completed yet. Is it normal that the smoke tests take so long? Or are the tests not running yet?

@CodaFi
Copy link
Contributor

CodaFi commented Mar 28, 2017

Executing tests requires privileges.

@tonisuter
Copy link
Contributor Author

@CodaFi Ok, thanks. That makes sense :-)

@rudkx Ok, array literals such as [1 as Int, 1.0, nil] should now produce the error message: error: heterogeneous collection literal could only be inferred to '[Any?]'; add explicit type annotation if this is intentional.

@rudkx rudkx self-assigned this Apr 5, 2017
@rudkx
Copy link
Contributor

rudkx commented Apr 6, 2017

@swift-ci Please smoke test

@rudkx
Copy link
Contributor

rudkx commented Apr 6, 2017

On the Type::join function - I don't think any changes are needed there as it will already properly handle joining types involving optional. This change is really about using binding T? rather than T if there is a constraint for the type variable involving ExpressibleByNilLiteral.

@rudkx rudkx merged commit 96b01c4 into swiftlang:master Apr 6, 2017
@rudkx
Copy link
Contributor

rudkx commented Apr 6, 2017

@tonisuter Thanks for the fixes!

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.

4 participants