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-6971] Single line closure cannot infer type, but multiline can #49519

Closed
mbrandonw opened this issue Feb 9, 2018 · 5 comments
Closed

[SR-6971] Single line closure cannot infer type, but multiline can #49519

mbrandonw opened this issue Feb 9, 2018 · 5 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself type checker Area → compiler: Semantic analysis

Comments

@mbrandonw
Copy link
Contributor

Previous ID SR-6971
Radar None
Original Reporter @mbrandonw
Type Bug
Status Closed
Resolution Done
Environment

Xcode 9.2

Swift 4.0.x

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, TypeChecker
Assignee @xedin
Priority Medium

md5: 782051cebbe7a6fa9664c4e339e3853e

Issue Description:

Consider this simple `chunk` addition to `Array`:

extension Array {
  func chunk(_ n: Int) -> [Array] {
    return stride(from: 0, to: self.count, by: n)
      .map { idx in
        Array(self.dropFirst(idx).prefix(n))
    }
  }
}

This currently does not compile. Even if I add return types and explicit `return` to the closure:

extension Array {
  func chunk(_ n: Int) -> [Array] {
    return stride(from: 0, to: self.count, by: n)
      .map { idx -> Array in
        return Array(self.dropFirst(idx).prefix(n))
    }
  }
}

However, if I break this to a multiline closure, it will then work, even without explicit types in the closure:

extension Array {
  func chunk(_ n: Int) -> [Array] {
    return stride(from: 0, to: self.count, by: n)
      .map { idx in
        let tmp = self.dropFirst(idx).prefix(n)
        return Array(tmp)
    }
  }
}

Even weirder, it doesn't seem to depend on the contents of the extra line in the closure. Even a print statement somehow kicks it into shape:

extension Array {
  func chunk(_ n: Int) -> [Array] {
    return stride(from: 0, to: self.count, by: n)
      .map { idx in
        print("")
        return Array(self.dropFirst(idx).prefix(n))
    }
  }
}
@mbrandonw
Copy link
Contributor Author

Update: specify the full type of the closure fixes it:

.map { (idx: Int) -> Array in

@belkadan
Copy link
Contributor

As you probably know, multi-statement closures are different from single-expression closures in that the type must be determined without looking at the body. This is an interesting case where the body seems to be making things more ambiguous.

The good news is that your example seems to work on master. @xedin, do you know if this made it into Swift 4.1?

@xedin
Copy link
Member

xedin commented Feb 12, 2018

@belkadan Yes, there are multiple issues which got fixed to make this work and all of them are merged in 4.1, I've tried with one of the latest 4.1 toolchains too to make sure that everything works.

@mbrandonw Thanks for the report! Please use the latest nightly toolchain of 4.1 branch to verify that everything works as expected.

@mbrandonw
Copy link
Contributor Author

@xedin, @belkadan just tested in 4.1 and it is indeed fixed

@xedin
Copy link
Member

xedin commented Feb 23, 2018

Thanks, @mbrandonw!

@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
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

3 participants