Skip to content

Commit 99856ed

Browse files
authored
Merge pull request swiftlang#29655 from xedin/rdar-41416758
[ConstraintSystem] Make variadics work with anonymous closure parameters
2 parents c722b1a + 07a69c4 commit 99856ed

File tree

3 files changed

+38
-22
lines changed

3 files changed

+38
-22
lines changed

include/swift/AST/Types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2853,6 +2853,10 @@ class AnyFunctionType : public TypeBase {
28532853
Param getWithoutLabel() const { return Param(Ty, Identifier(), Flags); }
28542854

28552855
Param withType(Type newType) const { return Param(newType, Label, Flags); }
2856+
2857+
Param withFlags(ParameterTypeFlags flags) const {
2858+
return Param(Ty, Label, flags);
2859+
}
28562860
};
28572861

28582862
class CanParam : public Param {

lib/Sema/CSSimplify.cpp

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6596,14 +6596,29 @@ static Type getFunctionBuilderTypeFor(ConstraintSystem &cs, unsigned paramIdx,
65966596
bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
65976597
Type contextualType,
65986598
ConstraintLocatorBuilder locator) {
6599+
auto getContextualParamAt =
6600+
[&contextualType](unsigned index) -> Optional<AnyFunctionType::Param> {
6601+
auto *fnType = contextualType->getAs<FunctionType>();
6602+
return fnType && fnType->getNumParams() > index
6603+
? fnType->getParams()[index]
6604+
: Optional<AnyFunctionType::Param>();
6605+
};
6606+
65996607
auto *closureLocator = typeVar->getImpl().getLocator();
66006608
auto *closure = cast<ClosureExpr>(closureLocator->getAnchor());
6601-
6602-
auto *closureType = getClosureType(closure);
6609+
auto *inferredClosureType = getClosureType(closure);
66036610

66046611
auto *paramList = closure->getParameters();
6612+
SmallVector<AnyFunctionType::Param, 4> parameters;
66056613
for (unsigned i = 0, n = paramList->size(); i != n; ++i) {
6606-
const auto &param = closureType->getParams()[i];
6614+
auto param = inferredClosureType->getParams()[i];
6615+
6616+
// In case of anonymous parameters let's infer flags from context
6617+
// that helps to infer variadic and inout earlier.
6618+
if (closure->hasAnonymousClosureVars()) {
6619+
if (auto contextualParam = getContextualParamAt(i))
6620+
param = param.withFlags(contextualParam->getParameterFlags());
6621+
}
66076622

66086623
Type internalType;
66096624

@@ -6617,17 +6632,25 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
66176632
auto *paramLoc =
66186633
getConstraintLocator(closure, LocatorPathElt::TupleElement(i));
66196634

6620-
internalType = createTypeVariable(paramLoc, TVO_CanBindToLValue |
6621-
TVO_CanBindToNoEscape);
6635+
auto *typeVar = createTypeVariable(paramLoc, TVO_CanBindToLValue |
6636+
TVO_CanBindToNoEscape);
6637+
6638+
// If external parameter is variadic it translates into an array in
6639+
// the body of the closure.
6640+
internalType =
6641+
param.isVariadic() ? ArraySliceType::get(typeVar) : Type(typeVar);
66226642

66236643
auto externalType = param.getOldType();
6624-
addConstraint(ConstraintKind::BindParam, externalType, internalType,
6625-
paramLoc);
6644+
addConstraint(ConstraintKind::BindParam, externalType, typeVar, paramLoc);
66266645
}
66276646

66286647
setType(paramList->get(i), internalType);
6648+
parameters.push_back(param);
66296649
}
66306650

6651+
auto closureType =
6652+
FunctionType::get(parameters, inferredClosureType->getResult(),
6653+
inferredClosureType->getExtInfo());
66316654
assignFixedType(typeVar, closureType, closureLocator);
66326655

66336656
if (auto last = locator.last()) {

test/expr/closure/anonymous.swift

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,38 +13,27 @@ func takesIntArray(_: [Int]) { }
1313
func takesVariadicInt(_: (Int...) -> ()) { }
1414
func takesVariadicIntInt(_: (Int, Int...) -> ()) { }
1515

16-
func takesVariadicGeneric<T>(_ f: (T...) -> ()) { }
16+
func takesVariadicGeneric<T>(_ f: (T...) -> ()) { } // expected-note {{in call to function 'takesVariadicGeneric'}}
1717

1818
func variadic() {
1919
// These work
2020

21-
// FIXME: Not anymore: rdar://41416758
2221
takesVariadicInt({let _ = $0})
23-
// expected-error@-1 {{cannot convert value of type '(_) -> ()' to expected argument type '(Int...) -> ()'}}
2422
takesVariadicInt({let _: [Int] = $0})
25-
// expected-error@-1 {{cannot convert value of type '(_) -> ()' to expected argument type '(Int...) -> ()'}}
2623

2724
let _: (Int...) -> () = {let _: [Int] = $0}
28-
// expected-error@-1 {{cannot convert value of type '(_) -> ()' to specified type '(Int...) -> ()'}}
2925

3026
takesVariadicInt({takesIntArray($0)})
31-
// expected-error@-1 {{cannot pass array of type '[Int]' as variadic arguments of type 'Int'}}
3227

3328
let _: (Int...) -> () = {takesIntArray($0)}
34-
// expected-error@-1 {{cannot pass array of type '[Int]' as variadic arguments of type 'Int'}}
3529

3630
takesVariadicGeneric({takesIntArray($0)})
37-
// expected-error@-1 {{cannot pass array of type '[Int]' as variadic arguments of type 'Int'}}
38-
39-
// FIXME(diagnostics): Problems here are related to multi-statement closure bodies not being type-checked together with
40-
// enclosing context.
4131

32+
// FIXME: Problem here is related to multi-statement closure body not being type-checked together with
33+
// enclosing context. We could have inferred `$0` to be `[Int]` if `let` was a part of constraint system.
4234
takesVariadicGeneric({let _: [Int] = $0})
43-
// expected-error@-1 {{cannot convert value of type '(_) -> ()' to expected argument type '(_...) -> ()'}}
35+
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
4436

4537
takesVariadicIntInt({_ = $0; takesIntArray($1)})
46-
// expected-error@-1 {{cannot convert value of type '(_, _) -> ()' to expected argument type '(Int, Int...) -> ()'}}
47-
4838
takesVariadicIntInt({_ = $0; let _: [Int] = $1})
49-
// expected-error@-1 {{cannot convert value of type '(_, _) -> ()' to expected argument type '(Int, Int...) -> ()'}}
5039
}

0 commit comments

Comments
 (0)