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-6921] Inconsistent reflection results on enums with 0 or 1 labeled associated value #49470

Open
swift-ci opened this issue Feb 4, 2018 · 5 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. standard library Area: Standard library umbrella

Comments

@swift-ci
Copy link
Collaborator

swift-ci commented Feb 4, 2018

Previous ID SR-6921
Radar None
Original Reporter 0x7fs (JIRA User)
Type Bug
Environment

Swift 4

Xcode 9.2 (9C40b)

macOS High Sierra 10.13.2 (17C205)

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

md5: d0b3c63e56f6b4684e808dc344ba2769

Issue Description:

I've encountered what I believe to be a bug in how enums with labeled associated values handle being reflected upon. It appears that there is an inconsistency between how a case with one associated value is handled, compared to a case with two or more. Consider the following example:

enum TestEnum {
    case first
    case second(label1: String)
    case third(label1: String, label2: String)
    case fourth(label1: String, label2: String, label3: String)
}
 
print(Array(Mirror(reflecting: TestEnum.first).children))
print(Array(Mirror(reflecting: TestEnum.second(label1: "Hello")).children))
print(Array(Mirror(reflecting: TestEnum.third(label1: "Hello", label2: "Swift")).children))
print(Array(Mirror(reflecting: TestEnum.fourth(label1: "Hello", label2: "Swift", label3: "Team")).children))

In the first line of output, it is not expected that the enum with no associated values should have no children. It may not have a "value", but it should probably have a "label" of "first" to be consistent with the cases below.

The second line contains the "label" indicating the name of the enum case, and a "value" indicating its associated value. There is no mention of "label1" the actual label for the associated value.

This is inconsistent with the last two lines of output for the enum cases with 2 and 3 associated values, which each show both the name of the enum case, as well as a mapping between the names of the labels for each associated value, and the associated values themselves.

[]
[(label: Optional("second"), value: "Hello")]
[(label: Optional("third"), value: (label1: "Hello", label2: "Swift"))]
[(label: Optional("fourth"), value: (label1: "Hello", label2: "Swift", label3: "Team"))]

To be clear, I would have expected the output above to look more like this:

[(label: Optional("first"), value: nil)]
[(label: Optional("second"), value: (label1: "Hello"))]
[(label: Optional("third"), value: (label1: "Hello", label2: "Swift"))]
[(label: Optional("fourth"), value: (label1: "Hello", label2: "Swift", label3: "Team"))]
@belkadan
Copy link
Contributor

belkadan commented Feb 5, 2018

That can't be the output either, because that's what you'd get for case first(Int?) when it's nil.

@jckarter, who owns Mirror these days?

@jckarter
Copy link
Member

jckarter commented Feb 5, 2018

Playgrounds is the primary consumer. From what I recall, this was the behavior we designed. cwakamo (JIRA User) what do you think about changing it?

@swift-ci
Copy link
Collaborator Author

Comment by Aaron Von Gauss (JIRA)

I think this is mostly working as they intended in the sense that it appears to be reflecting how an instance is implemented rather than an abstract reflection model. If you change the print statements in the original code to dump statements for the mirror result it better illustrates the situation.

- __lldb_expr_41.TestEnum.first__lldb_expr_41.TestEnum.second
  - second: "Hello"__lldb_expr_41.TestEnum.thirdthird: (2 elements)
    - label1: "Hello"
    - label2: "Swift"__lldb_expr_41.TestEnum.fourthfourth: (3 elements)
    - label1: "Hello"
    - label2: "Swift"
    - label3: "Team"

The third and fourth branches in the output above containing the associated values are tuples values and tuples by definition in Swift contain 2 or more items. With that in mind, it can't use the same structure for the second enumeration value as there is only one associated value so it returns the actual value.

I think its definitely a bug though that its returning "second" rather than "label1" for the child element label (Child.label).

@swift-ci
Copy link
Collaborator Author

swift-ci commented Jun 5, 2018

Comment by Aaron Von Gauss (JIRA)

The behavior seems to have changed with the toolchains included in the Xcode 10 beta. It is now returning a different structure with the expected label of "label1" for the second enum example as shown below (converting original example print calls to dump).

- 0 elements1 element
  ▿ (2 elements)
    ▿ label: Optional("second")
      - some: "second"value: (1 element)
      - label1: "Hello"1 element
  ▿ (2 elements)
    ▿ label: Optional("third")
      - some: "third"value: (2 elements)
      - label1: "Hello"
      - label2: "Swift"1 element
  ▿ (2 elements)
    ▿ label: Optional("fourth")
      - some: "fourth"value: (3 elements)
      - label1: "Hello"
      - label2: "Swift"
      - label3: "Team"

For me, this resolves the issue of not being able to retrieve the label of a single value enumeration. My error inspector is very appreciative.

@swift-ci
Copy link
Collaborator Author

Comment by James Froggatt (JIRA)

Hi, I've linked to this issue in SR-12255 as it seems related.

@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