Skip to content

Commit f1bd6d2

Browse files
committed
Attempt at fixing #61733
1 parent 447e524 commit f1bd6d2

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

lib/Sema/CSSimplify.cpp

+48
Original file line numberDiff line numberDiff line change
@@ -7968,6 +7968,54 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
79687968
if (conformance) {
79697969
return recordConformance(conformance);
79707970
}
7971+
7972+
// Consider the following debug constraint output:
7973+
//
7974+
// (attempting disjunction choice (P)? bind ($T1)? [deep equality] [[locator@0x11d9ac9f0 [Call@/Users/nuriamari/git/swift-project/swift/test/Constraints/scratch.swift:10:3 -> apply argument -> comparing call argument #0 to parameter #0]]];
7975+
// (considering -> $T1 conforms to P [[locator@0x11d9ac6d8 [DeclRef@/Users/nuriamari/git/swift-project/swift/test/Constraints/scratch.swift:10:3 -> opened generic -> type parameter requirement #0 (conformance)]]];
7976+
// (simplification result:
7977+
// (attempting fix [fix: add missing protocol conformance] @ locator@0x11d9ac6d8 [DeclRef@/Users/nuriamari/git/swift-project/swift/test/Constraints/scratch.swift:10:3 -> opened generic -> type parameter requirement #0 (conformance)])
7978+
// (increasing 'applied fix' score by 1)
7979+
// (removed constraint: $T1 conforms to P [[locator@0x11d9ac6d8 [DeclRef@/Users/nuriamari/git/swift-project/swift/test/Constraints/scratch.swift:10:3 -> opened generic -> type parameter requirement #0 (conformance)]]];)
7980+
// )
7981+
// (outcome: simplified)
7982+
// )
7983+
// (Changes:
7984+
// (Newly Bound:
7985+
// > $T1 := (P)
7986+
// )
7987+
// (Removed Constraint:
7988+
// > $T1 conforms to P [[locator@0x11d9ac6d8 [DeclRef@/Users/nuriamari/git/swift-project/swift/test/Constraints/scratch.swift:10:3 -> opened generic -> type parameter requirement #0 (conformance)]]];
7989+
// )
7990+
// )
7991+
// (found solution: [component: applied fix(s), value: 1])
7992+
// )
7993+
//
7994+
//
7995+
// In this method, we are simplifying the `$T1 conforms to P` constraint. As a result of the above disjunction, we have `any P`, that is existential P as a fixed type for $T1.
7996+
// Unless we open this existential, we will never pass the above lookup conformance and continue to report the `MissingConformance` fix.
7997+
//
7998+
// By opening the existential, I have removed all errors from the test case, which obviously isn't what we want. We want to only open
7999+
// the existential when we are trying to bind `(any P)? to ($T1)?` and we've recorded a `ForceOptional` fix. The trouble is I don't have
8000+
// enough context here to know this. I don't know how we arrived at `any P` as a fixed type for `$T1`.
8001+
//
8002+
// It seems like this change needs to be made elsewhere, but I'm not sure where. A method like `matchDeepEqualityTypes` gives us more context,
8003+
// but I'm not sure how to safely persist the opening of the existential until the conformance lookup above. Conceptually
8004+
// I understand that we are opening the existential so we can bind its underlying type to $T1, but I don't really understand
8005+
// what lasting side effects the below call to `openExistentialType` has on the constraint system if any.
8006+
8007+
if (shouldAttemptFixes()) {
8008+
if (type->isExistentialType()) {
8009+
type = openExistentialType(type, loc).first;
8010+
8011+
auto conformance = DC->getParentModule()->lookupConformance(
8012+
type, protocol, /*allowMissing=*/true);
8013+
if (conformance) {
8014+
return recordConformance(conformance);
8015+
}
8016+
}
8017+
}
8018+
79718019
} break;
79728020

79738021
default:

test/Constraints/scratch.swift

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %target-typecheck-verify-swift
2+
protocol P {}
3+
4+
struct S: P {}
5+
6+
func takesOptionalP(_: (some P)?) {}
7+
8+
func passOptional(value: (any P)?) {
9+
takesOptionalP(value) // expected-error{{asdf}}
10+
}

0 commit comments

Comments
 (0)