Navigation Menu

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-13794] AnyHashable can become nested unexpectedly when a generic type is specialized with an AnyHashable #56191

Open
erichoracek opened this issue Oct 30, 2020 · 2 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. standard library Area: Standard library umbrella

Comments

@erichoracek
Copy link

Previous ID SR-13794
Radar rdar://problem/70892591
Original Reporter @erichoracek
Type Bug
Environment

Xcode 12.0.1 (12A7300)

Swift 5.3

MacOS 10.15.7 (19H2)

Additional Detail from JIRA
Votes 0
Component/s Standard Library
Labels Bug
Assignee None
Priority Medium

md5: 51b4efcf2c28e45704e2c7537e05b3db

Issue Description:

With the following code

enum E {
  case c
}

protocol P {
  var erasedID: AnyHashable { get }
}

struct S<ID: Hashable> {
  var id: ID
}

extension S: P {
  var erasedID: AnyHashable { id }
}

let a = S<AnyHashable>(id: E.c)
print(a.id.debugDescription)
print(a.erasedID.debugDescription)
print(a.id == a.erasedID)

let b = S<E>(id: E.c)
print(b.id)
print(b.erasedID.debugDescription)
print(b.id as AnyHashable == b.erasedID)

The output is unexpectedly the following:

AnyHashable(E.c)
AnyHashable(AnyHashable(E.c))
false

c
AnyHashable(E.c)
true

In the first case with S<AnyHashable> there are two layers of nested AnyHashable in a.erasedID, which results in a.id not being equal to a.erasedID. This is unexpected behavior, and intuitively as a language consumer you would not expect AnyHashables to be possible to double-box like this.

In the second case with S<E>, it functions as expected, with b.id equal to b.erasedID.

You can fix this behavior by updating the `erasedID` to the following, but it feels like something that the language should handle automatically:

var erasedID: AnyHashable {
  let erased = id as AnyHashable
  if let base = erased.base as? AnyHashable {
    return base
  }
  return id
}
@typesanitizer
Copy link

@swift-ci create

@lorentey
Copy link
Member

AnyHashable is currently lacking a custom AnyHashable representation – I expect we'll be able to add it when we gain conformance availability.

@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. standard library Area: Standard library umbrella
Projects
None yet
Development

No branches or pull requests

3 participants