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-851] Result of dropFirst differs between 2.1.1 and 2.2 #43463

Closed
jepers opened this issue Mar 1, 2016 · 9 comments
Closed

[SR-851] Result of dropFirst differs between 2.1.1 and 2.2 #43463

jepers opened this issue Mar 1, 2016 · 9 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself regression swift 2.2

Comments

@jepers
Copy link

jepers commented Mar 1, 2016

Previous ID SR-851
Radar rdar://problem/24908900
Original Reporter @jepers
Type Bug
Status Closed
Resolution Done
Additional Detail from JIRA
Votes 2
Component/s Compiler
Labels Bug, 2.2Regression
Assignee @xedin
Priority Medium

md5: 82315efa37acb8595f74c537261fd2a5

is duplicated by:

  • SR-461 prefix() chained after filter() confuses type inference when used on a sequence that uses AnyGenerator
  • SR-1595 Chained subsequence operations confuse the compiler
  • SR-1856 prefix() chained after sorted() and before map() confuses type inference in 3.0
  • SR-1996 Accessing count inline on a filtered Lazy{Map,Filter}Collection causes ambiguous use of filter()

Issue Description:

Example 1/2
Compiles with Swift 2.1.1 but not with Swift 2.2:

$ cat > test.swift
let x = 1
let a = ["a", "b", "c", "d"]
let b = a.dropFirst(x).prefix(2) // OK in both 2.1.1 and 2.2
let c = a.dropFirst(1).prefix(2) // Ok in 2.1.1, but error in 2.2: Ambigous use of 'dropFirst'
print(b)
print(c)

$ sudo xcode-select -s /Applications/Xcode.app
$ swiftc --version
Apple Swift version 2.1.1 (swiftlang-700.1.101.15 clang-700.1.81)
Target: x86_64-apple-darwin15.3.0

$ swiftc test.swift
$ ./test
["b", "c"]
["b", "c"]

$ sudo xcode-select -s /Applications/Xcode-beta.app
$ swiftc --version
Apple Swift version 2.2 (swiftlang-703.0.17.2 clang-703.0.26)
Target: x86_64-apple-macosx10.9

$ swiftc test.swift
test.swift:4:9: error: ambiguous use of 'dropFirst'
let c = a.dropFirst(1).prefix(2) // Error: Ambigous use of 'dropFirst'
        ^
Swift.CollectionType:13:17: note: found this candidate
    public func dropFirst(n: Int) -> Self.SubSequence
                ^
Swift.SequenceType:7:17: note: found this candidate
    public func dropFirst(n: Int) -> AnySequence<Self.Generator.Element>

Example 2/2
Compiles in both 2.1.1 and 2.2 but type of result is ArraySlice<String> for 2.1.1 and AnySequence<String> for 2.2:

$ cat > test.swift
let x = 1
let a = ["a", "b", "c", "d"]
let b = a.dropFirst(x).prefix(2) // OK in both 2.1.1 and 2.2, but b will have different type.
print(b)

$ sudo xcode-select -s /Applications/Xcode.app
$ swiftc --version
Apple Swift version 2.1.1 (swiftlang-700.1.101.15 clang-700.1.81)
Target: x86_64-apple-darwin15.3.0

$ swiftc test.swift
$ ./test
["b", "c"]

$ sudo xcode-select -s /Applications/Xcode-beta.app
$ swiftc --version
Apple Swift version 2.2 (swiftlang-703.0.17.2 clang-703.0.26)
Target: x86_64-apple-macosx10.9

$ swiftc test.swift
$ ./test
AnySequence<String>(_box: Swift._SequenceBox<Swift.AnySequence<Swift.String>>)
@moiseev
Copy link
Mannequin

moiseev mannequin commented Mar 2, 2016

@jepers, out of curiosity, how did you find this issue? I would love to see non-artificial examples.
As a workaround please try to use `dropFrist(1 as Int).prefix(2)`.

@jepers
Copy link
Author

jepers commented Mar 2, 2016

I can't remember the exact situation / actual code but I had something like this (in Swift 2.2):

    let i = 1, j = 2
    let a = [1, 2, 3, 4, 5, 6]
    let b = a.dropFirst(i).prefix(j)
    print(b)

Which compiles fine. And then I needed to change that into something like this:

    let i = 1, j = 2
    let a = [1, 2, 3, 4, 5, 6]
    let b = a.dropFirst(i + j).prefix(j) // Note that dropFirst is now given i + j instead of just i
    print(b)

and I was surprised to see that this modification should cause a compile time error ("Ambiguous use of 'dropFirst'").

Your workaround works for this example, so this compiles fine:

    let i = 1, j = 2
    let a = [1, 2, 3, 4, 5, 6]
    let b = a.dropFirst((i + j) as Int).prefix(j)
    print(b)

But this leads to the disturbing conclusion that the type of i + j (an Int + an Int) apparently isn't Int in this particular context, and it makes me wonder what other incarnations of this strangeness I might bump into ...

Also, I wanted an ArraySlice<Int> (which is what I'll get in Swift 2.1.1) and not an AnySequence<Int> (which is what I get in 2.2).

The following example shows how unintuitive / surprising this behavior is in 2.2:

    let i = 1, j = 2
    let a = [1, 2, 3, 4, 5, 6]
    let b = a.dropFirst().prefix(j)
    let c = a.dropFirst(i).prefix(j)
    print(b) // Prints [2, 3]
    print(c) // Prints AnySequence<Int>(_box: Swift._SequenceBox<Swift.AnySequence<Swift.Int>>)

I mean, who would expect b and c to have different types?
(b is an ArraySlice<Int>)

@moiseev
Copy link
Mannequin

moiseev mannequin commented Mar 2, 2016

For typechecker, expression `i` is totally different from `i + j`, AFAIK. It IS `Int`, but it is not known immediately, and rather is inferred along with all other types using all the available constrains (actually, adding an extra constrain).

Another thing you might want to try in order to help type checker is add `as ArraySlice<YOUR_TYPE_HERE>` at the end of the whole expression, or specify a type for your `b` variable explicitly as `ArraySlice<...>`. This way you should be able to get what you expect without an extra `Array(...)` call.

@jepers
Copy link
Author

jepers commented Mar 2, 2016

Yes, I ended up specifying the type to ArraySlice ... And for what it's worth: I had no problems moving on with my code. My point here is that, well, this is a bug report and this is obviously demonstrating one or more bugs. : )

@moiseev
Copy link
Mannequin

moiseev mannequin commented Mar 2, 2016

Absolutely. All the bug reports are appreciated. It was not obvious whether you were able to find a workaround, so I tried to give you one... or two.
Thanks!

@jepers
Copy link
Author

jepers commented Aug 4, 2016

Issue remains in Xcode 8 beta 4, with std toolchain and with dev snapshot 2016-08-04.

@jepers
Copy link
Author

jepers commented Oct 12, 2016

Issue remains in Xcode 8 GM, 8.1 beta 1, 2 and 3.

@palimondo
Copy link
Mannequin

palimondo mannequin commented Mar 2, 2017

In Swift version 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1),

@xedin
Copy link
Member

xedin commented Nov 18, 2017

This is resolved by #12520 going to prefer SubSequence over AnySequence and both solutions are going to result in ArraySlice. @jepers please verify and resolve.

@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 regression swift 2.2
Projects
None yet
Development

No branches or pull requests

3 participants