Skip to content

Type inference fails when a literal is passed to a generic function and the return value is applied to a binary operator. #65061

@kishikawakatsumi

Description

@kishikawakatsumi

Description

When I pass a literal expression as an argument to a generic function and compare its return value to another literal with a binary operator, the == case is not a problem, but ! = causes the type inference failure and a compilation error.

I have confirmed that some cases compile correctly in Swift 4.2.3. Also, the difference between == and ! = operators gives different type inference results on either side, which seems odd. So this seems to be some kind of regression in Swift 5.

Steps to reproduce

  1. Define the following generic function:
func f<T>(_ val: T) -> T { return val }
  1. Use the function in the following code segments a and b:
let i = 0 _ = f([0]).firstIndex(of: 0) == i // a _ = f([0]).firstIndex(of: 0) != i // b // Error

The Swift compiler produces a compilation error for code segment b, while code segment a compiles without any issues. The only difference between the two is which binary operator is used. The error message is Value of optional type 'Int?' must be unwrapped to a value of type 'Int'. The only difference between the two segments is the binary operator. It seems odd that it would cause an error in one of them.

Both codes compile correctly in Swift 4.2.3. It appears to be a regression that probably occurred in Swift 5.
See https://swiftfiddle.com/ky3flhj6wnc3hkxw6ft4lfnx7q

Expected behavior

Both code segments a and b should compile without errors, as the only difference between them is the binary operator.

Environment

  • Swift compiler version info
    • from Swift version 5.0 (swift-5.0-RELEASE) to Swift version 5.8 (swift-5.8-RELEASE) and 5.9-dev (LLVM 8ef0b2ab8e410d9, Swift 76d60fde58eab47)
  • Xcode version info Xcode 14.3 Build version 14E222b

Additional context

As a temporary workaround, defining an overloaded function as follows fixes the compilation error:

func f<T>(_ val: [T]) -> [T] { return val }

This indicates that the issue might be related to the compiler's inability to infer the type from the literals correctly.

Similar cases

Float literals

This happens not only with array literals but also with float and string literals.

The following code causes a compile error Ambiguous use of operator '==' for line a.
This problem does not occur in the Linux environment but only in the Mac environment, resulting in a compile error.

 _ = f(0.0) == 1 // a _ = f(0.0) != 1 // b

This problem does not occur if the following overloads are provided:

func f(_ val: Float) -> Float { return val }
String literals

The following code causes a compile error Value of optional type 'String.Element?' (aka 'Optional<Character>') must be unwrapped to a value of type 'String.Element' (aka 'Character') for line b.

let c: Character = "a" _ = f("").first == c // a _ = f("").first != c // b

This issue occurs in both Linux and Mac environments.

Also, as in the first example, it does not occur in a Swift 4.2.4 environment. See https://swiftfiddle.com/b2o6hyjbfjdhre47tkovyq4oja

As with the other examples, this problem does not occur if you provide the following overloads:

func f(_ val: String) -> String { return val }

Metadata

Metadata

Assignees

Labels

bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.compilerThe Swift compiler itselfgenericsFeature: generic declarations and typesoperatorsFeature: operatorsregressionswift 5.9type checkerArea → compiler: Semantic analysistype inferenceFeature: type inferencetypesFeature: typesunexpected errorBug: Unexpected error

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions