Skip to content
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

[SR-7318] Type interference sometimes is wrong on equality check #49866

Open
swift-ci opened this issue Mar 31, 2018 · 6 comments
Open

[SR-7318] Type interference sometimes is wrong on equality check #49866

swift-ci opened this issue Mar 31, 2018 · 6 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself regression swift 4.1 type checker Area → compiler: Semantic analysis

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-7318
Radar rdar://problem/39143381
Original Reporter vhbit (JIRA User)
Type Bug
Environment

Swift 4.1 from Xcode 9.3 (9E145)

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, 4.1Regression, TypeChecker
Assignee None
Priority Medium

md5: 30fd51ff3ed5acce33a3e35add5f858d

Issue Description:

It seems that sometimes when checking equality with `.none` the other argument is promoted to Optional which causes unexpected results compared to Swift 4.0

enum Foo {
    case none
    case always
    case smart
}

struct Bar {
    let foo: Foo
}

let x: Foo = .none
x != .none // false as expected

let y: Bar? = Bar(foo: x)
(y?.foo ?? .none) != .none // unexpectedly returns true, worked fine on Swift 4.0
(y?.foo ?? .none) != Foo.none // false as expected
@belkadan
Copy link
Contributor

belkadan commented Apr 3, 2018

Hm. What changed in 4.1? @xedin?

@swift-ci create

@belkadan
Copy link
Contributor

belkadan commented Apr 3, 2018

(May be a standard library change, we'll see.)

@xedin
Copy link
Member

xedin commented Apr 3, 2018

Interesting, since `Optional` is now `Equitable` if '.none', on the right-hand side, is spelled without the base `!=` is inferred as (Foo?, Foo?) -> Bool`, if it's spelled as `Foo.none` it's inferred as `(Foo, Foo) -> Bool`, because `.none` could be interpreted as `Optional.none` instead of `Foo.none`.

/cc @moiseev

@xedin
Copy link
Member

xedin commented Apr 3, 2018

/cc @DougGregor

@DougGregor
Copy link
Member

As @xedin notes, `.none` could be interpreted either way. The `Foo.none` solution is better, in the sense that it doesn't require an optional injection on the left-hand side of the `!=` operator, so Swift 4.0 was correct to choose it.

@xedin
Copy link
Member

xedin commented Apr 12, 2018

@DougGregor Bigger issue here is that both `!=` overloads that form solutions are declared in protocol extensions, one on `Equatable` `(Self, Self) -> Bool` and another one on `Optional` `(Wrapped?, Wrapped?) -> Bool` and the latter one is more specialized because it's conditional on associated type, that's why we pick `.none` to be `Optional.none` in that example.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself regression swift 4.1 type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

5 participants