Skip to content

[4.1] Restore a very narrow function argument conversion for -swift-version 4. #14480

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 2 commits into from
Feb 8, 2018
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
9 changes: 6 additions & 3 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6127,9 +6127,12 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
// func bar() -> ((()) -> Void)? { return nil }
// foo(bar) // This expression should compile in Swift 3 mode
// ```
if (tc.getLangOpts().isSwiftVersion3()) {
auto obj1 = fromType->getAnyOptionalObjectType();
auto obj2 = toType->getAnyOptionalObjectType();
//
// See also: https://bugs.swift.org/browse/SR-6796
if (cs.getASTContext().isSwiftVersionAtLeast(3) &&
!cs.getASTContext().isSwiftVersionAtLeast(5)) {
auto obj1 = fromType->getOptionalObjectType();
auto obj2 = toType->getOptionalObjectType();

if (obj1 && obj2) {
auto *fn1 = obj1->getAs<AnyFunctionType>();
Expand Down
29 changes: 29 additions & 0 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,35 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
}
}

// https://bugs.swift.org/browse/SR-6796
// Add a super-narrow hack to allow:
// (()) -> T to be passed in place of () -> T
if (getASTContext().isSwiftVersionAtLeast(4) &&
!getASTContext().isSwiftVersionAtLeast(5)) {
SmallVector<LocatorPathElt, 4> path;
locator.getLocatorParts(path);

// Find the last path element, skipping GenericArgument elements
// so that we allow this exception in cases of optional types, and
// skipping OptionalPayload elements so that we allow this
// exception in cases of optional injection.
auto last = std::find_if(
path.rbegin(), path.rend(), [](LocatorPathElt &elt) -> bool {
return elt.getKind() != ConstraintLocator::GenericArgument &&
elt.getKind() != ConstraintLocator::OptionalPayload;
});

if (last != path.rend()) {
if (last->getKind() == ConstraintLocator::ApplyArgToParam) {
if (auto *paren1 = dyn_cast<ParenType>(func1Input.getPointer())) {
auto innerTy = paren1->getUnderlyingType();
if (func2Input->isVoid() && innerTy->isVoid())
func1Input = innerTy;
}
}
}
}

// Input types can be contravariant (or equal).
SmallVector<AnyFunctionType::Param, 4> func1Params;
SmallVector<AnyFunctionType::Param, 4> func2Params;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// RUN: %target-typecheck-verify-swift -swift-version 3

// Tests for tuple argument behavior in Swift 3, which was broken.
// The Swift 4 test is in test/Constraints/tuple_arguments.swift.
// The Swift 4 test is in test/Compatibility/tuple_arguments_4.swift.
// The test for the most recent version is in test/Constraints/tuple_arguments.swift.

// Key:
// - "Crashes in actual Swift 3" -- snippets which crashed in Swift 3.0.1.
Expand Down Expand Up @@ -1502,3 +1503,20 @@ do {
takeFn(fn: { (pair: (Int, Int?)) in } )
takeFn { (pair: (Int, Int?)) in }
}

// https://bugs.swift.org/browse/SR-6796
do {
func f(a: (() -> Void)? = nil) {}
func log<T>() -> ((T) -> Void)? { return nil }

f(a: log() as ((()) -> Void)?) // Allow ((()) -> Void)? to be passed in place of (() -> Void)?

func logNoOptional<T>() -> (T) -> Void { }
f(a: logNoOptional() as ((()) -> Void)) // Also allow the optional-injected form.

func g() {}
g(())

func h(_: ()) {}
h()
}
Loading