Skip to content

Commit f7b0a79

Browse files
author
Greg Titus
committed
Penalize type mismatches that lead to @dynamicMemberLookup types
1 parent 0350023 commit f7b0a79

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15269,12 +15269,19 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1526915269
// Passing a closure to a parameter that doesn't expect one should
1527015270
// be scored lower because there might be an overload that expects
1527115271
// a closure but has other issues e.g. wrong number of parameters.
15272-
if (!type2->lookThroughAllOptionalTypes()->is<FunctionType>()) {
15272+
auto nonOptional2 = type2->lookThroughAllOptionalTypes();
15273+
if (!nonOptional2->is<FunctionType>()) {
1527315274
auto argument = simplifyLocatorToAnchor(fix->getLocator());
1527415275
if (isExpr<ClosureExpr>(argument)) {
1527515276
impact += 2;
1527615277
}
1527715278
}
15279+
// A parameter expecting dynamic member lookup may mask other
15280+
// missing member errors. Discourage choosing this overload if
15281+
// there are other options.
15282+
if (nonOptional2->hasDynamicMemberLookupAttribute()) {
15283+
impact += 6;
15284+
}
1527815285

1527915286
// De-prioritize `Builtin.RawPointer` and `OpaquePointer` parameters
1528015287
// because they usually clash with generic parameter mismatches e.g.

test/Constraints/issue-74700.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
protocol Idable<ID> {
4+
associatedtype ID
5+
var id: ID { get }
6+
}
7+
func test74700() {
8+
@dynamicMemberLookup struct Binding<C> {
9+
subscript(dynamicMember member: String) -> String { "" }
10+
}
11+
struct ForEach<Data, ID, Content> where Data : RandomAccessCollection, ID: Hashable {
12+
init(_ data: Data, content: (Data.Element) -> Content) where ID == Data.Element.ID, Data.Element : Idable {}
13+
// expected-note@-1 {{where 'Data.Element' = 'User'}}
14+
init<C>(_ data: Binding<C>, content: (Binding<C.Element>) -> Content) where Data == Array<C>, ID == C.Element.ID, C : MutableCollection, C : RandomAccessCollection, C.Element : Idable, C.Index : Hashable {}
15+
}
16+
17+
struct User {
18+
let name: String // expected-note {{'name' declared here}}
19+
}
20+
21+
struct ContentView {
22+
let users: [User] = []
23+
func body() -> Void {
24+
ForEach(users) { user in // expected-error {{initializer 'init(_:content:)' requires that 'User' conform to 'Idable'}}
25+
return user.nam // expected-error {{value of type 'User' has no member 'nam'; did you mean 'name'?}}
26+
}
27+
}
28+
}
29+
}

0 commit comments

Comments
 (0)