Merge pull request #84715 from xedin/rdar-159401910

[Diagnostics] Fix a few issues with existential type mismatches
This commit is contained in:
Pavel Yaskevich
2025-10-07 09:39:36 -07:00
committed by GitHub
3 changed files with 51 additions and 11 deletions

View File

@@ -8750,7 +8750,36 @@ 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);
ArrayRef<LocatorPathElt> path = loc->getPath();
while (!path.empty()) {
if (!path.back().is<LocatorPathElt::InstanceType>())
break;
path = path.drop_back();
}
if (path.size() != loc->getPath().size()) {
loc = getConstraintLocator(loc->getAnchor(), path);
}
ConstraintFix *fix = nullptr;
if (loc->isLastElement<LocatorPathElt::ApplyArgToParam>()) {
fix = AllowArgumentMismatch::create(*this, type, protocol, loc);
} else if (loc->isLastElement<LocatorPathElt::ContextualType>()) {
fix = ContextualMismatch::create(*this, type, protocol, loc);
}
if (fix) {
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
}
}
return result;
}
void ConstraintSystem::recordSynthesizedConformance(
@@ -9124,6 +9153,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<LocatorPathElt::InstanceType>()) {
path.pop_back();
continue;
}
break;
}
@@ -9217,7 +9253,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
}
}
if (loc->isLastElement<LocatorPathElt::MemberRefBase>()) {
if (path.back().is<LocatorPathElt::MemberRefBase>()) {
auto *fix = ContextualMismatch::create(*this, protocolTy, type, loc);
if (!recordFix(fix))
return SolutionKind::Solved;
@@ -9227,7 +9263,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
// for example to `AnyHashable`.
if ((kind == ConstraintKind::ConformsTo ||
kind == ConstraintKind::NonisolatedConformsTo) &&
loc->isLastElement<LocatorPathElt::ApplyArgToParam>()) {
path.back().is<LocatorPathElt::ApplyArgToParam>()) {
auto *fix = AllowArgumentMismatch::create(*this, type, protocolTy, loc);
return recordFix(fix, /*impact=*/2) ? SolutionKind::Error
: SolutionKind::Solved;

View File

@@ -120,16 +120,20 @@ func parameterizedExistentials() {
pt = ppt // expected-error {{cannot assign value of type 'any PP4<Int>.Type' to type 'any P4<Int>.Type'}}
}
// https://github.com/swiftlang/swift/issues/83991
func testNestedMetatype() {
struct S: P {}
func bar<T>(_ x: T) -> T.Type { type(of: x) }
func foo(_ x: P.Type.Type) { }
func bar<T>(_ x: T) -> T.Type { }
func metaBar<T>(_ x: T) -> T.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))
// FIXME: Bad diagnostic
// https://github.com/swiftlang/swift/issues/83991
foo(bar(0)) // expected-error {{failed to produce diagnostic for expression}}
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'}}
}

View File

@@ -538,5 +538,5 @@ func testYap(_ y: Yapping<NC>) {
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'}}
}