Skip to content

Commit e159131

Browse files
authored
Merge pull request #37380 from hborla/property-wrapper-inference-crash
[ConstraintSystem] Fix a constraint system crash with property wrapper inference using the $ syntax.
2 parents 65b9a1c + c297070 commit e159131

File tree

8 files changed

+46
-17
lines changed

8 files changed

+46
-17
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6819,13 +6819,9 @@ bool UnableToInferClosureParameterType::diagnoseAsError() {
68196819
llvm::SmallString<16> id;
68206820
llvm::raw_svector_ostream OS(id);
68216821

6822-
if (PD->isAnonClosureParam()) {
6823-
OS << "$" << paramIdx;
6824-
} else {
6825-
OS << "'" << PD->getParameterName() << "'";
6826-
}
6822+
OS << "'" << PD->getParameterName() << "'";
68276823

6828-
auto loc = PD->isAnonClosureParam() ? getLoc() : PD->getLoc();
6824+
auto loc = PD->isImplicit() ? getLoc() : PD->getLoc();
68296825
emitDiagnosticAt(loc, diag::cannot_infer_closure_parameter_type, OS.str());
68306826
return true;
68316827
}

lib/Sema/CSFix.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,11 +1545,7 @@ std::string SpecifyClosureParameterType::getName() const {
15451545
auto *PD = closure->getParameters()->get(paramLoc.getIndex());
15461546

15471547
OS << "specify type for parameter ";
1548-
if (PD->isAnonClosureParam()) {
1549-
OS << "$" << paramLoc.getIndex();
1550-
} else {
1551-
OS << "'" << PD->getParameterName() << "'";
1552-
}
1548+
OS << "'" << PD->getParameterName() << "'";
15531549

15541550
return OS.str();
15551551
}

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/Constraints/closures.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ struct S_3520 {
499499
func sr3520_set_via_closure<S, T>(_ closure: (inout S, T) -> ()) {} // expected-note {{in call to function 'sr3520_set_via_closure'}}
500500
sr3520_set_via_closure({ $0.number1 = $1 })
501501
// expected-error@-1 {{generic parameter 'S' could not be inferred}}
502-
// expected-error@-2 {{unable to infer type of a closure parameter $1 in the current context}}
502+
// expected-error@-2 {{unable to infer type of a closure parameter '$1' in the current context}}
503503

504504
// SR-3073: UnresolvedDotExpr in single expression closure
505505

test/Constraints/diagnostics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ func r18800223(_ i : Int) {
296296
}
297297

298298
// <rdar://problem/21883806> Bogus "'_' can only appear in a pattern or on the left side of an assignment" is back
299-
_ = { $0 } // expected-error {{unable to infer type of a closure parameter $0 in the current context}}
299+
_ = { $0 } // expected-error {{unable to infer type of a closure parameter '$0' in the current context}}
300300

301301

302302

test/Constraints/one_way_closure_params.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
func testBasic() {
44
let _: (Float) -> Float = { $0 + 1 }
55

6-
let _ = { $0 + 1 } // expected-error{{unable to infer type of a closure parameter $0 in the current context}}
6+
let _ = { $0 + 1 } // expected-error{{unable to infer type of a closure parameter '$0' in the current context}}
77
}
88

test/Sema/property_wrapper_parameter_invalid.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,30 @@ 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+
// expected-error@+1 {{unable to infer type of a closure parameter '$value' in the current context}}
228+
testGenericClosure { $value in }
229+
testGenericClosure { ($value: ProjectionWrapper<Int>) in } // okay
230+
231+
func testExtraParameter(_ closure: () -> Void) {}
232+
// expected-error@+1 {{contextual closure type '() -> Void' expects 0 arguments, but 1 was used in closure body}}
233+
testExtraParameter { $value in }
234+
}

test/expr/closure/anonymous.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func variadic() {
3232
// FIXME: Problem here is related to multi-statement closure body not being type-checked together with
3333
// enclosing context. We could have inferred `$0` to be `[Int]` if `let` was a part of constraint system.
3434
takesVariadicGeneric({let _: [Int] = $0})
35-
// expected-error@-1 {{unable to infer type of a closure parameter $0 in the current context}}
35+
// expected-error@-1 {{unable to infer type of a closure parameter '$0' in the current context}}
3636

3737
takesVariadicIntInt({_ = $0; takesIntArray($1)})
3838
takesVariadicIntInt({_ = $0; let _: [Int] = $1})

0 commit comments

Comments
 (0)