From 140acd6a0d5e8f7ab6b5047fb26e33ad7d5b8f6a Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 18 Jan 2017 22:24:20 -0800 Subject: [PATCH] SILGen: Fix yet another 'argument labels ignored if parameter type is Any' thing In Swift 3, we had a bug where you could provide argument labels to a function call taking a single Any parameter, even if the parameter did not have a label. This mostly worked (with asserts off!) but in fact it would crash in SILGen if you were calling an enum case constructor. Since this 'feature' has been promoted from 'works on accident' to 'still a hack but guarded by Swift 3 mode and exists on purpose', fix the crash, even though Swift 3 could not compile the code in question. Also add a Swift 3 mode check to the earlier SILGen hack, so that when/if we remove Swift 3 mode it will be obvious that this code is now dead too. --- lib/SILGen/SILGenExpr.cpp | 16 +++++++++++++--- test/Compatibility/tuple_arguments.swift | 7 +++++++ test/Constraints/tuple_arguments.swift | 7 +++++++ test/SILGen/argument_shuffle_swift3.swift | 11 +++++++++++ 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 95ea6f58985e1..670a8eade2495 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -1926,7 +1926,14 @@ RValue RValueEmitter::visitTupleShuffleExpr(TupleShuffleExpr *E, // If we're emitting into an initialization, we can try shuffling the // elements of the initialization. if (Initialization *I = C.getEmitInto()) { - if (I->canSplitIntoTupleElements()) { + // In Swift 3 mode, we might be stripping off labels from a + // one-element tuple; the destination type is a ParenType in + // that case. + // + // FIXME: Remove this eventually. + if (I->canSplitIntoTupleElements() && + !(isa(E->getType().getPointer()) && + SGF.getASTContext().isSwiftVersion3())) { emitTupleShuffleExprInto(*this, E, I); return RValue(); } @@ -1943,10 +1950,13 @@ RValue RValueEmitter::visitTupleShuffleExpr(TupleShuffleExpr *E, // Prepare a new tuple to hold the shuffled result. RValue result(E->getType()->getCanonicalType()); - // In Swift 3 mode, we might have to shuffle off labels. + // In Swift 3 mode, we might be stripping off labels from a + // one-element tuple; the destination type is a ParenType in + // that case. // // FIXME: Remove this eventually. - if (isa(E->getType().getPointer())) { + if (isa(E->getType().getPointer()) && + SGF.getASTContext().isSwiftVersion3()) { assert(E->getElementMapping().size() == 1); auto shuffleIndex = E->getElementMapping()[0]; assert(shuffleIndex != TupleShuffleExpr::DefaultInitialize && diff --git a/test/Compatibility/tuple_arguments.swift b/test/Compatibility/tuple_arguments.swift index 59645ecbbab49..03ae3bb138c4d 100644 --- a/test/Compatibility/tuple_arguments.swift +++ b/test/Compatibility/tuple_arguments.swift @@ -1274,6 +1274,10 @@ do { // with single 'Any' parameter func takesAny(_: Any) {} +enum HasAnyCase { + case any(_: Any) +} + do { let fn: (Any) -> () = { _ in } @@ -1282,4 +1286,7 @@ do { takesAny(123) takesAny(data: 123) + + _ = HasAnyCase.any(123) + _ = HasAnyCase.any(data: 123) } diff --git a/test/Constraints/tuple_arguments.swift b/test/Constraints/tuple_arguments.swift index 75c7b22533989..6c9b449890872 100644 --- a/test/Constraints/tuple_arguments.swift +++ b/test/Constraints/tuple_arguments.swift @@ -1259,6 +1259,10 @@ do { // with single 'Any' parameter func takesAny(_: Any) {} +enum HasAnyCase { + case any(_: Any) +} + do { let fn: (Any) -> () = { _ in } @@ -1267,4 +1271,7 @@ do { takesAny(123) takesAny(data: 123) // expected-error {{extraneous argument label 'data:' in call}} + + _ = HasAnyCase.any(123) + _ = HasAnyCase.any(data: 123) // expected-error {{extraneous argument label 'data:' in call}} } diff --git a/test/SILGen/argument_shuffle_swift3.swift b/test/SILGen/argument_shuffle_swift3.swift index 4ccb9af93138c..f009080bb7330 100644 --- a/test/SILGen/argument_shuffle_swift3.swift +++ b/test/SILGen/argument_shuffle_swift3.swift @@ -2,6 +2,10 @@ func fn(_: Any) {} +enum HasAnyCase { + case any(_: Any) +} + // CHECK-LABEL: sil hidden @_TF23argument_shuffle_swift31gFT1xP__T_ : $@convention(thin) (@in Any) -> () { func g(x: Any) { // CHECK: [[FN:%.*]] = function_ref @_TF23argument_shuffle_swift32fnFP_T_ : $@convention(thin) (@in Any) -> () @@ -10,5 +14,12 @@ func g(x: Any) { // CHECK: [[FN:%.*]] = function_ref @_TF23argument_shuffle_swift32fnFP_T_ : $@convention(thin) (@in Any) -> () // CHECK: apply [[FN:%.*]]({{.*}}) : $@convention(thin) (@in Any) -> () fn(data: x) + + // CHECK: inject_enum_addr {{.*}} : $*HasAnyCase, #HasAnyCase.any!enumelt.1 + _ = HasAnyCase.any(123) + + // CHECK: inject_enum_addr {{.*}} : $*HasAnyCase, #HasAnyCase.any!enumelt.1 + _ = HasAnyCase.any(data: 123) + // CHECK: return }