Skip to content

In Swift 3 mode, allow "tuple unsplatting" in certain cases. #7102

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

Merged
merged 1 commit into from
Jan 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,21 @@ matchCallArguments(ConstraintSystem &cs, ConstraintKind kind,
getCalleeDeclAndArgs(cs, locator, argLabelsScratch);
auto params = decomposeParamType(paramType, callee, calleeLevel);

if (callee && cs.getASTContext().isSwiftVersion3()
&& argType->is<TupleType>()) {
// Hack: In Swift 3 mode, accept `foo(x, y)` for `foo((x, y))` when the
// callee is a function-typed property or an enum constructor whose
// argument is a single unlabeled type parameter.
if (auto *prop = dyn_cast<VarDecl>(callee)) {
auto *fnType = prop->getInterfaceType()->getAs<AnyFunctionType>();
if (fnType && fnType->getInput()->isTypeParameter())
argType = ParenType::get(cs.getASTContext(), argType);
} else if (auto *enumCtor = dyn_cast<EnumElementDecl>(callee)) {
if (enumCtor->getArgumentInterfaceType()->isTypeParameter())
argType = ParenType::get(cs.getASTContext(), argType);
}
}

// Extract the arguments.
auto args = decomposeArgType(argType, argLabels);

Expand Down
116 changes: 113 additions & 3 deletions test/Compatibility/tuple_arguments.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,18 @@
// but now crash. These are bugs in Swift 3 mode that should be fixed.

func concrete(_ x: Int) {}
func concreteLabeled(x: Int) {}
func concreteTwo(_ x: Int, _ y: Int) {} // expected-note 3 {{'concreteTwo' declared here}}
func concreteTuple(_ x: (Int, Int)) {}

do {
concrete(3)
concrete((3))

concreteLabeled(x: 3)
concreteLabeled(x: (3))
concreteLabeled((x: 3)) // expected-error {{missing argument label 'x:' in call}}

concreteTwo(3, 4)
concreteTwo((3, 4)) // expected-error {{missing argument for parameter #2 in call}}

Expand Down Expand Up @@ -72,6 +77,7 @@ do {
}

func generic<T>(_ x: T) {}
func genericLabeled<T>(x: T) {}
func genericTwo<T, U>(_ x: T, _ y: U) {} // expected-note 5 {{'genericTwo' declared here}}
func genericTuple<T, U>(_ x: (T, U)) {}

Expand All @@ -81,6 +87,11 @@ do {
generic((3))
generic((3, 4))

genericLabeled(x: 3)
genericLabeled(x: 3, 4) // expected-error {{extra argument in call}}
genericLabeled(x: (3))
genericLabeled(x: (3, 4))

genericTwo(3, 4)
genericTwo((3, 4)) // expected-error {{missing argument for parameter #2 in call}}

Expand Down Expand Up @@ -250,6 +261,7 @@ do {

extension Concrete {
func generic<T>(_ x: T) {}
func genericLabeled<T>(x: T) {}
func genericTwo<T, U>(_ x: T, _ y: U) {} // expected-note 5 {{'genericTwo' declared here}}
func genericTuple<T, U>(_ x: (T, U)) {}
}
Expand All @@ -262,6 +274,11 @@ do {
s.generic((3))
s.generic((3, 4))

s.genericLabeled(x: 3)
s.genericLabeled(x: 3, 4) // expected-error {{extra argument in call}}
s.genericLabeled(x: (3))
s.genericLabeled(x: (3, 4))

s.genericTwo(3, 4)
s.genericTwo((3, 4)) // expected-error {{missing argument for parameter #2 in call}}

Expand Down Expand Up @@ -378,6 +395,7 @@ do {

extension Concrete {
mutating func mutatingGeneric<T>(_ x: T) {}
mutating func mutatingGenericLabeled<T>(x: T) {}
mutating func mutatingGenericTwo<T, U>(_ x: T, _ y: U) {} // expected-note 5 {{'mutatingGenericTwo' declared here}}
mutating func mutatingGenericTuple<T, U>(_ x: (T, U)) {}
}
Expand All @@ -390,6 +408,11 @@ do {
s.mutatingGeneric((3))
s.mutatingGeneric((3, 4))

s.mutatingGenericLabeled(x: 3)
s.mutatingGenericLabeled(x: 3, 4) // expected-error {{extra argument in call}}
s.mutatingGenericLabeled(x: (3))
s.mutatingGenericLabeled(x: (3, 4))

s.mutatingGenericTwo(3, 4)
s.mutatingGenericTwo((3, 4)) // expected-error {{missing argument for parameter #2 in call}}

Expand Down Expand Up @@ -512,12 +535,19 @@ struct InitTuple {
init(_ x: (Int, Int)) {}
}

struct InitLabeledTuple {
init(x: (Int, Int)) {}
}

do {
_ = InitTwo(3, 4)
_ = InitTwo((3, 4)) // expected-error {{missing argument for parameter #2 in call}}

_ = InitTuple(3, 4) // expected-error {{extra argument in call}}
_ = InitTuple((3, 4))

_ = InitLabeledTuple(x: 3, 4) // expected-error {{extra argument in call}}
_ = InitLabeledTuple(x: (3, 4))
}

do {
Expand Down Expand Up @@ -556,6 +586,10 @@ struct SubscriptTuple {
subscript(_ x: (Int, Int)) -> Int { get { return 0 } set { } }
}

struct SubscriptLabeledTuple {
subscript(x x: (Int, Int)) -> Int { get { return 0 } set { } }
}

do {
let s1 = SubscriptTwo()
_ = s1[3, 4]
Expand All @@ -564,6 +598,10 @@ do {
let s2 = SubscriptTuple()
_ = s2[3, 4] // expected-error {{extra argument in call}}
_ = s2[(3, 4)]

let s3 = SubscriptLabeledTuple()
_ = s3[x: 3, 4] // expected-error {{extra argument in call}}
_ = s3[x: (3, 4)]
}

do {
Expand Down Expand Up @@ -601,6 +639,7 @@ do {
enum Enum {
case two(Int, Int) // expected-note 3 {{'two' declared here}}
case tuple((Int, Int))
case labeledTuple(x: (Int, Int))
}

do {
Expand All @@ -609,6 +648,9 @@ do {

_ = Enum.tuple(3, 4) // expected-error {{extra argument in call}}
_ = Enum.tuple((3, 4))

_ = Enum.labeledTuple(x: 3, 4) // expected-error {{extra argument in call}}
_ = Enum.labeledTuple(x: (3, 4))
}

do {
Expand Down Expand Up @@ -643,6 +685,7 @@ struct Generic<T> {}

extension Generic {
func generic(_ x: T) {}
func genericLabeled(x: T) {}
func genericTwo(_ x: T, _ y: T) {} // expected-note 2 {{'genericTwo' declared here}}
func genericTuple(_ x: (T, T)) {}
}
Expand All @@ -653,6 +696,9 @@ do {
s.generic(3.0)
s.generic((3.0))

s.genericLabeled(x: 3.0)
s.genericLabeled(x: (3.0))

s.genericTwo(3.0, 4.0)
s.genericTwo((3.0, 4.0)) // expected-error {{missing argument for parameter #2 in call}}

Expand All @@ -663,6 +709,9 @@ do {

sTwo.generic(3.0, 4.0) // expected-error {{extra argument in call}}
sTwo.generic((3.0, 4.0))

sTwo.genericLabeled(x: 3.0, 4.0) // expected-error {{extra argument in call}}
sTwo.genericLabeled(x: (3.0, 4.0))
}

do {
Expand Down Expand Up @@ -717,6 +766,7 @@ do {

extension Generic {
mutating func mutatingGeneric(_ x: T) {}
mutating func mutatingGenericLabeled(x: T) {}
mutating func mutatingGenericTwo(_ x: T, _ y: T) {} // expected-note 2 {{'mutatingGenericTwo' declared here}}
mutating func mutatingGenericTuple(_ x: (T, T)) {}
}
Expand All @@ -727,6 +777,9 @@ do {
s.mutatingGeneric(3.0)
s.mutatingGeneric((3.0))

s.mutatingGenericLabeled(x: 3.0)
s.mutatingGenericLabeled(x: (3.0))

s.mutatingGenericTwo(3.0, 4.0)
s.mutatingGenericTwo((3.0, 4.0)) // expected-error {{missing argument for parameter #2 in call}}

Expand All @@ -737,6 +790,9 @@ do {

sTwo.mutatingGeneric(3.0, 4.0) // expected-error {{extra argument in call}}
sTwo.mutatingGeneric((3.0, 4.0))

sTwo.mutatingGenericLabeled(x: 3.0, 4.0) // expected-error {{extra argument in call}}
sTwo.mutatingGenericLabeled(x: (3.0, 4.0))
}

do {
Expand Down Expand Up @@ -809,7 +865,7 @@ do {

let sTwo = Generic<(Double, Double)>()

sTwo.genericFunction(3.0, 4.0) // FIXME: Diagnoses in Swift 3 mode // expected-error {{extra argument in call}}
sTwo.genericFunction(3.0, 4.0)
sTwo.genericFunction((3.0, 4.0)) // Does not diagnose in Swift 3 mode
}

Expand Down Expand Up @@ -858,7 +914,7 @@ do {

var sTwo = Generic<(Double, Double)>()

sTwo.genericFunction(a, b) // FIXME: Diagnoses in Swift 3 mode // expected-error {{extra argument in call}}
sTwo.genericFunction(a, b)
sTwo.genericFunction((a, b)) // Does not diagnose in Swift 3 mode
sTwo.genericFunction(d) // Does not diagnose in Swift 3 mode
}
Expand All @@ -867,6 +923,10 @@ struct GenericInit<T> { // expected-note 2 {{'T' declared as parameter to type '
init(_ x: T) {}
}

struct GenericInitLabeled<T> {
init(x: T) {}
}

struct GenericInitTwo<T> {
init(_ x: T, _ y: T) {} // expected-note 8 {{'init' declared here}}
}
Expand All @@ -875,26 +935,42 @@ struct GenericInitTuple<T> {
init(_ x: (T, T)) {}
}

struct GenericInitLabeledTuple<T> {
init(x: (T, T)) {}
}

do {
_ = GenericInit(3, 4)
_ = GenericInit((3, 4))

_ = GenericInitLabeled(x: 3, 4) // expected-error {{extra argument in call}}
_ = GenericInitLabeled(x: (3, 4))

_ = GenericInitTwo(3, 4)
_ = GenericInitTwo((3, 4)) // expected-error {{missing argument for parameter #2 in call}}

_ = GenericInitTuple(3, 4) // expected-error {{extra argument in call}}
_ = GenericInitTuple((3, 4))

_ = GenericInitLabeledTuple(x: 3, 4) // expected-error {{extra argument in call}}
_ = GenericInitLabeledTuple(x: (3, 4))
}

do {
_ = GenericInit<(Int, Int)>(3, 4)
_ = GenericInit<(Int, Int)>((3, 4)) // expected-error {{expression type 'GenericInit<(Int, Int)>' is ambiguous without more context}}

_ = GenericInitLabeled<(Int, Int)>(x: 3, 4) // expected-error {{extra argument in call}}
_ = GenericInitLabeled<(Int, Int)>(x: (3, 4))

_ = GenericInitTwo<Int>(3, 4)
_ = GenericInitTwo<Int>((3, 4)) // expected-error {{missing argument for parameter #2 in call}}

_ = GenericInitTuple<Int>(3, 4) // expected-error {{extra argument in call}}
_ = GenericInitTuple<Int>((3, 4))

_ = GenericInitLabeledTuple<Int>(x: 3, 4) // expected-error {{extra argument in call}}
_ = GenericInitLabeledTuple<Int>(x: (3, 4))
}

do {
Expand Down Expand Up @@ -973,6 +1049,10 @@ struct GenericSubscript<T> {
subscript(_ x: T) -> Int { get { return 0 } set { } }
}

struct GenericSubscriptLabeled<T> {
subscript(x x: T) -> Int { get { return 0 } set { } }
}

struct GenericSubscriptTwo<T> {
subscript(_ x: T, _ y: T) -> Int { get { return 0 } set { } } // expected-note {{'subscript' declared here}}
}
Expand All @@ -981,18 +1061,30 @@ struct GenericSubscriptTuple<T> {
subscript(_ x: (T, T)) -> Int { get { return 0 } set { } }
}

struct GenericSubscriptLabeledTuple<T> {
subscript(x x: (T, T)) -> Int { get { return 0 } set { } }
}

do {
let s1 = GenericSubscript<(Double, Double)>()
_ = s1[3.0, 4.0]
_ = s1[(3.0, 4.0)] // expected-error {{expression type 'Int' is ambiguous without more context}}

let s1a = GenericSubscriptLabeled<(Double, Double)>()
_ = s1a [x: 3.0, 4.0] // expected-error {{extra argument in call}}
_ = s1a [x: (3.0, 4.0)]

let s2 = GenericSubscriptTwo<Double>()
_ = s2[3.0, 4.0]
_ = s2[(3.0, 4.0)] // expected-error {{missing argument for parameter #2 in call}}

let s3 = GenericSubscriptTuple<Double>()
_ = s3[3.0, 4.0] // expected-error {{extra argument in call}}
_ = s3[(3.0, 4.0)]

let s3a = GenericSubscriptLabeledTuple<Double>()
_ = s3a[x: 3.0, 4.0] // expected-error {{extra argument in call}}
_ = s3a[x: (3.0, 4.0)]
}

do {
Expand Down Expand Up @@ -1039,6 +1131,7 @@ do {

enum GenericEnum<T> {
case one(T)
case labeled(x: T)
case two(T, T) // expected-note 8 {{'two' declared here}}
case tuple((T, T))
}
Expand All @@ -1047,6 +1140,11 @@ do {
_ = GenericEnum.one(3, 4)
_ = GenericEnum.one((3, 4))

_ = GenericEnum.labeled(x: 3, 4) // expected-error {{extra argument in call}}
_ = GenericEnum.labeled(x: (3, 4))
_ = GenericEnum.labeled(3, 4) // expected-error {{extra argument in call}}
_ = GenericEnum.labeled((3, 4)) // expected-error {{missing argument label 'x:' in call}}

_ = GenericEnum.two(3, 4)
_ = GenericEnum.two((3, 4)) // expected-error {{missing argument for parameter #2 in call}}

Expand All @@ -1055,9 +1153,14 @@ do {
}

do {
_ = GenericEnum<(Int, Int)>.one(3, 4) // FIXME: Diagnoses in Swift 3 mode // expected-error {{extra argument in call}}
_ = GenericEnum<(Int, Int)>.one(3, 4)
_ = GenericEnum<(Int, Int)>.one((3, 4)) // Does not diagnose in Swift 3 mode

_ = GenericEnum<(Int, Int)>.labeled(x: 3, 4) // expected-error {{extra argument in call}}
_ = GenericEnum<(Int, Int)>.labeled(x: (3, 4))
_ = GenericEnum<(Int, Int)>.labeled(3, 4) // expected-error {{extra argument in call}}
_ = GenericEnum<(Int, Int)>.labeled((3, 4)) // expected-error {{missing argument label 'x:' in call}}

_ = GenericEnum<Int>.two(3, 4)
_ = GenericEnum<Int>.two((3, 4)) // expected-error {{missing argument for parameter #2 in call}}

Expand Down Expand Up @@ -1143,6 +1246,7 @@ protocol Protocol {

extension Protocol {
func requirement(_ x: Element) {}
func requirementLabeled(x: Element) {}
func requirementTwo(_ x: Element, _ y: Element) {} // expected-note 2 {{'requirementTwo' declared here}}
func requirementTuple(_ x: (Element, Element)) {}
}
Expand All @@ -1157,6 +1261,9 @@ do {
s.requirement(3.0)
s.requirement((3.0))

s.requirementLabeled(x: 3.0)
s.requirementLabeled(x: (3.0))

s.requirementTwo(3.0, 4.0)
s.requirementTwo((3.0, 4.0)) // expected-error {{missing argument for parameter #2 in call}}

Expand All @@ -1167,6 +1274,9 @@ do {

sTwo.requirement(3.0, 4.0) // expected-error {{extra argument in call}}
sTwo.requirement((3.0, 4.0))

sTwo.requirementLabeled(x: 3.0, 4.0) // expected-error {{extra argument in call}}
sTwo.requirementLabeled(x: (3.0, 4.0))
}

do {
Expand Down
Loading