Skip to content

Commit ef58f6a

Browse files
committed
[ConstraintSystem] If the contextual parameter type doesn't exist when
resolving a closure, create a new type variable for inferred property wrapper types.
1 parent 833a453 commit ef58f6a

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8682,8 +8682,18 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
86828682
Type wrappedValueType;
86838683

86848684
if (paramDecl->hasImplicitPropertyWrapper()) {
8685-
backingType = getContextualParamAt(i)->getPlainType();
8686-
wrappedValueType = createTypeVariable(getConstraintLocator(locator),
8685+
if (auto contextualType = getContextualParamAt(i)) {
8686+
backingType = contextualType->getPlainType();
8687+
} else {
8688+
// There may not be a contextual parameter type if the contextual
8689+
// type is not a function type or if closure body declares too many
8690+
// parameters.
8691+
auto *paramLoc =
8692+
getConstraintLocator(closure, LocatorPathElt::TupleElement(i));
8693+
backingType = createTypeVariable(paramLoc, TVO_CanBindToHole);
8694+
}
8695+
8696+
wrappedValueType = createTypeVariable(getConstraintLocator(paramDecl),
86878697
TVO_CanBindToHole | TVO_CanBindToLValue);
86888698
} else {
86898699
auto *wrapperAttr = paramDecl->getAttachedPropertyWrappers().front();

test/Sema/property_wrapper_parameter_invalid.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,32 @@ struct OptionalWrapper<Value> { // expected-note {{'Value' declared as parameter
205205
// expected-error@+2 {{generic parameter 'Value' could not be inferred}} expected-note@+2 {{}}
206206
// expected-error@+1 {{property type 'Int' does not match 'wrappedValue' type 'Value?'}}
207207
func testWrappedValueMismatch(@OptionalWrapper value: Int) {}
208+
209+
@propertyWrapper
210+
struct ProjectionWrapper<Value> {
211+
var wrappedValue: Value
212+
var projectedValue: Self { self }
213+
init(projectedValue: Self) { self = projectedValue }
214+
}
215+
216+
func testInvalidWrapperInference() {
217+
struct S<V> {
218+
static func test(_ keyPath: KeyPath<V, String>) {} // expected-note {{'test' declared here}}
219+
}
220+
221+
// expected-error@+1 {{trailing closure passed to parameter of type 'KeyPath<Int, String>' that does not accept a closure}}
222+
S<Int>.test { $value in }
223+
// expected-error@+1 {{cannot convert value of type '(_) -> ()' to expected argument type 'KeyPath<Int, String>'}}
224+
S<Int>.test({ $value in })
225+
226+
func testGenericClosure<T>(_ closure: T) {}
227+
// FIXME: the following error should use the name of the closure parameter.
228+
// It's not anonymous, even though it starts with $
229+
// expected-error@+1 {{unable to infer type of a closure parameter $0 in the current context}}
230+
testGenericClosure { $value in }
231+
testGenericClosure { ($value: ProjectionWrapper<Int>) in } // okay
232+
233+
func testExtraParameter(_ closure: () -> Void) {}
234+
// expected-error@+1 {{contextual closure type '() -> Void' expects 0 arguments, but 1 was used in closure body}}
235+
testExtraParameter { $value in }
236+
}

0 commit comments

Comments
 (0)