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-13216] Assigning through keypath in single expression closure gives erroneous error #55656

Closed
swift-ci opened this issue Jul 14, 2020 · 4 comments
Labels

Comments

@swift-ci
Copy link
Collaborator

swift-ci commented Jul 14, 2020

Previous ID SR-13216
Radar None
Original Reporter jumhyn (JIRA User)
Type Bug
Status Closed
Resolution Done
Additional Detail from JIRA
Votes 1
Component/s
Labels Bug
Assignee None
Priority Medium

md5: 1b759cb2cce514f6334edc01fc6eb787

Issue Description:

struct S {
    var x: String?
}


func mutated<Value>(
    from value: Value,
    _ mutation: (inout Value) -> Void
) -> Value {
    var value = value
    mutation(&value)
    return value
}


func makeSTransformer(
    _ kp: WritableKeyPath<S, String?>
) -> (S) -> S {
    return { s in
        let value = ""
        return mutated(from: s) { updatedS in
            updatedS[keyPath: kp] = value
        }
    }
}

The above code results in the error: "Value of optional type 'String?' must be unwrapped. If we add an explicit return, it compiles without error:

struct S {
    var x: String?
}


func mutated<Value>(
    from value: Value,
    _ mutation: (inout Value) -> Void
) -> Value {
    var value = value
    mutation(&value)
    return value
}


func makeSTransformer(
    _ kp: WritableKeyPath<S, String?>
) -> (S) -> S {
    return { s in
        let value = ""
        return mutated(from: s) { updatedS in
            updatedS[keyPath: kp] = value
            return
        }
    }
}
@swift-ci
Copy link
Collaborator Author

swift-ci commented Jul 14, 2020

Comment by Frederick Kellison-Linn (JIRA)

From the output of `-debug-constraints` it looks like the constraint solver hits this issue when it attempts to solve the body as a single expression closure. Adding the explicit return causes the `updatedS[keyPath: kp] = value` line to be solved separately, which works as expected.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Jul 16, 2020

Comment by Frederick Kellison-Linn (JIRA)

Here's an even more minimal reproducer:

struct S {
    var x: String?
}


func mutated(_ mutation: (inout S) -> Void) {}


func makeSTransformer(_ kp: WritableKeyPath<S, String?>) {
    let value = ""
    mutated { updatedS in
        updatedS[keyPath: kp] = value
    }
}

@swift-ci
Copy link
Collaborator Author

swift-ci commented Jul 16, 2020

Comment by Frederick Kellison-Linn (JIRA)

More breadcrumbs: when `mutated` is passed a multi-expression closure, the type of `updatedS` is already resolved when we begin to type check the keypath assignment. Then, when we visit the subscript expression, member lookup finds the keypath subscript and generates the appropriate type variable for the key path argument. Later, we visit the `AssignExpr` and generate the type variable for the destination type. Since the argument type variable gets created first, we attempt the binding of the argument to `WritableKeyPath<S, String?>` before the binding of the destination to `String`.

In the single-expression case, we have not yet resolved the type of `updatedS` when we generate constraints for the subscript expression, so member lookup doesn't proceed. Then, the constraint generation for the assign expression gives us the type variable and constraints for the dest type based on the type of `value` (supertypes of `String`). Later, during simplification, we generate the appropriate constraints for the keypath subscript, but now the argument type variable is generated after the destination type of the assign expression. This results in us attempting to bind the dest type to `String` first, which causes the binding of `WritableKeypath<S, String?>` for the argument to fail (since it produces a dest type `String?` instead of `String?`).

@swift-ci
Copy link
Collaborator Author

swift-ci commented Jul 16, 2020

Comment by Frederick Kellison-Linn (JIRA)

Fixed by #32841

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant