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

Existential unexpectedly enables splatting behavior with variadic parameter #73925

Open
xwu opened this issue May 27, 2024 · 2 comments
Open
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. type checker Area → compiler: Semantic analysis variadic parameters Feature → declarations → function parameters: Variadic function parameters

Comments

@xwu
Copy link
Collaborator

xwu commented May 27, 2024

Description

Consider the following error:

func foo(_ x: Int...) { print("\(x.count) variadic argument(s) to 'foo'") }
func bar(_ y: Int...) { foo(y) }
// Error: cannot pass array of type 'Int...' as variadic arguments of type 'Int'

This behavior is deliberate, and there exists no splatting operator to enabling forwarding y as variadic arguments instead of a single argument—or is there?

Consider the following generic functions:

func foo2<T>(_ x: T...) { print("\(x.count) variadic argument(s) to 'foo2'") }
func bar2<T>(_ y: T...) { foo2(y) }
bar2(1, 2, 3) // prints "1 variadic argument(s) to 'foo2'"

This behavior is correct: y is passed as a single argument of type [Int] to foo2. But now consider the following functions that take existential arguments:

protocol P { }
extension Int: P { }
extension Array: P { }

func foo3(_ x: P...) { print("\(x.count) variadic argument(s) to 'foo3'") }
func bar3(_ y: P...) { foo3(y) }
bar3(1, 2, 3) // prints "3 variadic argument(s) to 'foo3'" (!!!)

By using an existential, we have unexpectedly enabled a splatting behavior that is not documented (or, afaict, intended).


Discussed in https://forums.swift.org/t/variadic-parameters-passing/72080/13

Reproduction

protocol P { }
extension Int: P { }
extension Array: P { }

func foo3(_ x: P...) { print("\(x.count) variadic argument(s) to 'foo3'") }
func bar3(_ y: P...) { foo3(y) }
bar3(1, 2, 3) // prints "3 variadic argument(s) to 'foo3'" (!!!)

Expected behavior

Prints "1 variadic argument(s) to 'foo3'" instead

Environment

Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-darwin23.3.0

Additional information

No response

@xwu xwu added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels labels May 27, 2024
@xwu
Copy link
Collaborator Author

xwu commented May 27, 2024

cc @slavapestov in case this is of interest to you :)

@xwu xwu changed the title Existential type unexpectedly enables splatting behavior with variadic parameter Existential unexpectedly enables splatting behavior with variadic parameter May 27, 2024
@slavapestov slavapestov reopened this May 28, 2024
@slavapestov
Copy link
Contributor

Reduced a bit:

protocol P { }
extension Int: P { }
extension Array: P { }

func foo3(_ x: P...) { print("\(x.count) variadic argument(s) to 'foo3'") }

let x: [P] = [1, 2, 3]
foo3(x)

The AST for the call to foo3() doesn't have a vararg_expansion_expr/array_expr:

  (top_level_code_decl range=[/Users/slava/src/swift/var.swift:8:1 - line:8:7]
    (brace_stmt implicit range=[/Users/slava/src/swift/var.swift:8:1 - line:8:7]
      (call_expr type="()" location=/Users/slava/src/swift/var.swift:8:1 range=[/Users/slava/src/swift/var.swift:8:1 - line:8:7] nothrow isolation_crossing="none"
        (declref_expr type="(any P...) -> ()" location=/Users/slava/src/swift/var.swift:8:1 range=[/Users/slava/src/swift/var.swift:8:1 - line:8:1] decl="var.(file).foo3@/Users/slava/src/swift/var.swift:5:6" function_ref=single)
        (argument_list
          (argument
            (declref_expr type="[any P]" location=/Users/slava/src/swift/var.swift:8:6 range=[/Users/slava/src/swift/var.swift:8:6 - line:8:6] decl="var.(file).x@/Users/slava/src/swift/var.swift:7:5" function_ref=unapplied)))))))

@hborla hborla added type checker Area → compiler: Semantic analysis variadic parameters Feature → declarations → function parameters: Variadic function parameters and removed triage needed This issue needs more specific labels labels Jul 14, 2024
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. type checker Area → compiler: Semantic analysis variadic parameters Feature → declarations → function parameters: Variadic function parameters
Projects
None yet
Development

No branches or pull requests

4 participants