swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.33k stars 10.34k forks source link

[SR-6729] URLQueryItem - Fails in Set Comparison #49278

Open swift-ci opened 6 years ago

swift-ci commented 6 years ago
Previous ID SR-6729
Radar None
Original Reporter sndmn (JIRA User)
Type Bug
Environment ubuntu 14.04
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Standard Library | |Labels | Bug, Linux | |Assignee | None | |Priority | Medium | md5: f2ff69b31de4428de85b37325a8afa2b

Issue Description:

On linux, comparison of URLQueryItems when within a Set fails intermittently. The issues seems to be Set related instead of URLQueryItem related, since comparing them directly always works as expected, but when placed into a Set the comparison fails about 40% of the time on linux. MacOS works as expected.

Below is a code Snippet, illustrating the problem.

```

let u1 = URLQueryItem(name: "intField", value: "1")

let u2 = URLQueryItem(name: "intField", value: "1")

let queryItems1 = [ u1 ]

let queryItems2 = [ u2 ]

assert(u1 == u2, "Individually: Works as expected")

assert(queryItems1, queryItems2, "Within an Array: Works as expected")

assert(Set(queryItems1) == Set(queryItems2), "Within a Set: Fails intermittently")

```

belkadan commented 6 years ago

cc @moiseev

ee21ea02-9d7a-4385-8c3c-ad21e8e490a8 commented 6 years ago

Sounds AnyHashable-related. @lorentey has been working with hashed collections recently.

lorentey commented 6 years ago

This looks like a problem with NSURLQueryItem in open-source Foundation: it overrides isEqual but not hash, so it inherits NSObject's hash value implementation that is based on object identity. This violates the requirement that object equality implies hashValue equality, leading to all sorts of issues with Set/Dictionary.

The snippet below should print true, true, but on Linux, it currently prints true, false.

import Foundation
let a = URLQueryItem(name: "intField", value: "1")
let b = URLQueryItem(name: "intField", value: "1")
print(a == b, a.hashValue == b.hashValue)

NSURLComponents seems to have the same issue.

cc @phausler

phausler commented 6 years ago

yup, that should definitely be defined (and is currently not), the objc version uses the name hash with the value hash (which seems like what we should be doing in swift).

Looks like a good starter bug.