From af909078e5b77c6534f25fa95fcfb5b43b771a5e Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 6 Oct 2025 09:34:34 -0700 Subject: [PATCH 1/3] [CSSimplify] Look through `InstanceType` while attempting to diagnose conformance failures Matching existential types could introduce `InstanceType` element at the end of the locator path, it's okay to look through them to diagnose the underlying issue. --- lib/Sema/CSSimplify.cpp | 11 +++++++++-- test/Constraints/existential_metatypes.swift | 9 ++++++--- test/Generics/inverse_generics.swift | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 27675a08699d0..600b19c4f3da3 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -9124,6 +9124,13 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint( continue; } + // Matching existentials could introduce constraints with `instance type` + // element at the end if the confirming type wasn't fully resolved. + if (path.back().is()) { + path.pop_back(); + continue; + } + break; } @@ -9217,7 +9224,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint( } } - if (loc->isLastElement()) { + if (path.back().is()) { auto *fix = ContextualMismatch::create(*this, protocolTy, type, loc); if (!recordFix(fix)) return SolutionKind::Solved; @@ -9227,7 +9234,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint( // for example to `AnyHashable`. if ((kind == ConstraintKind::ConformsTo || kind == ConstraintKind::NonisolatedConformsTo) && - loc->isLastElement()) { + path.back().is()) { auto *fix = AllowArgumentMismatch::create(*this, type, protocolTy, loc); return recordFix(fix, /*impact=*/2) ? SolutionKind::Error : SolutionKind::Solved; diff --git a/test/Constraints/existential_metatypes.swift b/test/Constraints/existential_metatypes.swift index 759f5fb69ec91..68aaa0f711442 100644 --- a/test/Constraints/existential_metatypes.swift +++ b/test/Constraints/existential_metatypes.swift @@ -124,12 +124,15 @@ func testNestedMetatype() { struct S: P {} func bar(_ x: T) -> T.Type { type(of: x) } - func foo(_ x: P.Type.Type) { } + func foo1(_ x: P.Type) {} + func foo2(_ x: P.Type.Type) { } + + foo1(bar(S.self)) // expected-error {{argument type 'S.Type' does not conform to expected type 'P'}} // Make sure we don't crash. - foo(bar(S.self)) + foo2(bar(S.self)) // FIXME: Bad diagnostic // https://github.com/swiftlang/swift/issues/83991 - foo(bar(0)) // expected-error {{failed to produce diagnostic for expression}} + foo2(bar(0)) // expected-error {{failed to produce diagnostic for expression}} } diff --git a/test/Generics/inverse_generics.swift b/test/Generics/inverse_generics.swift index 1fff8abf1c9a9..fdf886c9065de 100644 --- a/test/Generics/inverse_generics.swift +++ b/test/Generics/inverse_generics.swift @@ -538,5 +538,5 @@ func testYap(_ y: Yapping) { protocol Veggie: ~Copyable {} func generalized(_ x: Any.Type) {} func testMetatypes(_ t: (any Veggie & ~Copyable).Type) { - generalized(t) // expected-error {{cannot convert value of type '(any Veggie & ~Copyable).Type' to expected argument type 'any Any.Type'}} + generalized(t) // expected-error {{argument type 'any Veggie & ~Copyable' does not conform to expected type 'Copyable'}} } From 36fc1e6c4397299aa4d3441e8a0c273ffd64c9c6 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 6 Oct 2025 09:47:14 -0700 Subject: [PATCH 2/3] [CSSimplify] Diagnose an attempt to match non-existential type to an existential one Resolves: rdar://159401910 --- lib/Sema/CSSimplify.cpp | 22 +++++++++++++++++++- test/Constraints/existential_metatypes.swift | 7 +++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 600b19c4f3da3..22a2bf0ffafa6 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -8750,7 +8750,27 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint( return SolutionKind::Solved; } - return matchExistentialTypes(type, protocol, kind, flags, locator); + auto result = matchExistentialTypes(type, protocol, kind, flags, locator); + + if (shouldAttemptFixes() && result.isFailure()) { + auto *loc = getConstraintLocator(locator); + + if (loc->isLastElement()) + loc = getConstraintLocator(loc->getAnchor(), loc->getPath().drop_back()); + + ConstraintFix *fix = nullptr; + if (loc->isLastElement()) { + fix = AllowArgumentMismatch::create(*this, type, protocol, loc); + } else if (loc->isLastElement()) { + fix = ContextualMismatch::create(*this, type, protocol, loc); + } + + if (fix) { + return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved; + } + } + + return result; } void ConstraintSystem::recordSynthesizedConformance( diff --git a/test/Constraints/existential_metatypes.swift b/test/Constraints/existential_metatypes.swift index 68aaa0f711442..670cfb959614b 100644 --- a/test/Constraints/existential_metatypes.swift +++ b/test/Constraints/existential_metatypes.swift @@ -120,6 +120,8 @@ func parameterizedExistentials() { pt = ppt // expected-error {{cannot assign value of type 'any PP4.Type' to type 'any P4.Type'}} } +// https://github.com/swiftlang/swift/issues/83991 + func testNestedMetatype() { struct S: P {} @@ -131,8 +133,5 @@ func testNestedMetatype() { // Make sure we don't crash. foo2(bar(S.self)) - - // FIXME: Bad diagnostic - // https://github.com/swiftlang/swift/issues/83991 - foo2(bar(0)) // expected-error {{failed to produce diagnostic for expression}} + foo2(bar(0)) // expected-error {{cannot convert value of type 'Int' to expected argument type 'any P.Type'}} } From 15c56627b89fa1f6461a7bb348d7064074fb1d57 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 6 Oct 2025 14:01:28 -0700 Subject: [PATCH 3/3] [CSSimplify] Remove all `InstanceType` at the end of a locator to diagnose mismatched existential conversion --- lib/Sema/CSSimplify.cpp | 13 +++++++++++-- test/Constraints/existential_metatypes.swift | 4 +++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 22a2bf0ffafa6..60f328e9fbd83 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -8755,8 +8755,17 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint( if (shouldAttemptFixes() && result.isFailure()) { auto *loc = getConstraintLocator(locator); - if (loc->isLastElement()) - loc = getConstraintLocator(loc->getAnchor(), loc->getPath().drop_back()); + ArrayRef path = loc->getPath(); + while (!path.empty()) { + if (!path.back().is()) + break; + + path = path.drop_back(); + } + + if (path.size() != loc->getPath().size()) { + loc = getConstraintLocator(loc->getAnchor(), path); + } ConstraintFix *fix = nullptr; if (loc->isLastElement()) { diff --git a/test/Constraints/existential_metatypes.swift b/test/Constraints/existential_metatypes.swift index 670cfb959614b..baa0eb0ebdfc9 100644 --- a/test/Constraints/existential_metatypes.swift +++ b/test/Constraints/existential_metatypes.swift @@ -125,7 +125,8 @@ func parameterizedExistentials() { func testNestedMetatype() { struct S: P {} - func bar(_ x: T) -> T.Type { type(of: x) } + func bar(_ x: T) -> T.Type { } + func metaBar(_ x: T) -> T.Type.Type { } func foo1(_ x: P.Type) {} func foo2(_ x: P.Type.Type) { } @@ -134,4 +135,5 @@ func testNestedMetatype() { // Make sure we don't crash. foo2(bar(S.self)) foo2(bar(0)) // expected-error {{cannot convert value of type 'Int' to expected argument type 'any P.Type'}} + foo2(metaBar(0)) // expected-error {{argument type 'Int' does not conform to expected type 'P'}} }