mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #64036 from xedin/rdar-106054263
[CSSimplify] Detect and diagnose generic argument mismatches individually
This commit is contained in:
@@ -3748,15 +3748,23 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2,
|
||||
// Match up the generic arguments, exactly.
|
||||
|
||||
if (shouldAttemptFixes()) {
|
||||
auto *baseLoc =
|
||||
getConstraintLocator(locator, {LocatorPathElt::GenericType(bound1),
|
||||
LocatorPathElt::GenericType(bound2)});
|
||||
|
||||
auto argMatchingFlags =
|
||||
subflags | TMF_ApplyingFix | TMF_MatchingGenericArguments;
|
||||
|
||||
// Optionals have a lot of special diagnostics and only one
|
||||
// generic argument so if we' re dealing with one, don't produce generic
|
||||
// arguments mismatch fixes.
|
||||
if (bound1->getDecl()->isOptionalDecl())
|
||||
return matchDeepTypeArguments(*this, subflags, args1, args2, locator);
|
||||
return matchDeepTypeArguments(*this, argMatchingFlags, args1, args2,
|
||||
baseLoc);
|
||||
|
||||
SmallVector<unsigned, 4> mismatches;
|
||||
auto result = matchDeepTypeArguments(
|
||||
*this, subflags | TMF_ApplyingFix, args1, args2, locator,
|
||||
*this, argMatchingFlags, args1, args2, baseLoc,
|
||||
[&mismatches](unsigned position) { mismatches.push_back(position); });
|
||||
|
||||
if (mismatches.empty())
|
||||
@@ -4843,7 +4851,7 @@ static bool repairOutOfOrderArgumentsInBinaryFunction(
|
||||
/// \return true if at least some of the failures has been repaired
|
||||
/// successfully, which allows type matcher to continue.
|
||||
bool ConstraintSystem::repairFailures(
|
||||
Type lhs, Type rhs, ConstraintKind matchKind,
|
||||
Type lhs, Type rhs, ConstraintKind matchKind, TypeMatchOptions flags,
|
||||
SmallVectorImpl<RestrictionOrFix> &conversionsOrFixes,
|
||||
ConstraintLocatorBuilder locator) {
|
||||
SmallVector<LocatorPathElt, 4> path;
|
||||
@@ -5344,7 +5352,7 @@ bool ConstraintSystem::repairFailures(
|
||||
// let's re-attempt to repair without l-value conversion in the
|
||||
// locator to fix underlying type mismatch.
|
||||
if (path.back().is<LocatorPathElt::FunctionResult>()) {
|
||||
return repairFailures(lhs, rhs, matchKind, conversionsOrFixes,
|
||||
return repairFailures(lhs, rhs, matchKind, flags, conversionsOrFixes,
|
||||
getConstraintLocator(anchor, path));
|
||||
}
|
||||
|
||||
@@ -6133,7 +6141,7 @@ bool ConstraintSystem::repairFailures(
|
||||
if (!path.empty() && path.back().is<LocatorPathElt::PackType>())
|
||||
path.pop_back();
|
||||
|
||||
return repairFailures(lhs, rhs, matchKind, conversionsOrFixes,
|
||||
return repairFailures(lhs, rhs, matchKind, flags, conversionsOrFixes,
|
||||
getConstraintLocator(anchor, path));
|
||||
}
|
||||
|
||||
@@ -6369,7 +6377,8 @@ bool ConstraintSystem::repairFailures(
|
||||
// failure e.g. `String bind T.Element`, so let's drop the generic argument
|
||||
// path element and recurse in repairFailures to check and potentially
|
||||
// record the requirement failure fix.
|
||||
path.pop_back();
|
||||
auto genericArgElt =
|
||||
path.pop_back_val().castTo<LocatorPathElt::GenericArgument>();
|
||||
|
||||
// If we have something like ... -> type req # -> pack element #, we're
|
||||
// solving a requirement of the form T : P where T is a type parameter pack
|
||||
@@ -6377,11 +6386,61 @@ bool ConstraintSystem::repairFailures(
|
||||
path.pop_back();
|
||||
|
||||
if (!path.empty() && path.back().is<LocatorPathElt::AnyRequirement>()) {
|
||||
return repairFailures(lhs, rhs, matchKind, conversionsOrFixes,
|
||||
return repairFailures(lhs, rhs, matchKind, flags, conversionsOrFixes,
|
||||
getConstraintLocator(anchor, path));
|
||||
}
|
||||
|
||||
break;
|
||||
// When the solver sets `TMF_MatchingGenericArguments` it means
|
||||
// that it's matching generic argument pairs to identify any mismatches
|
||||
// as part of larger matching of two generic types. Letting this
|
||||
// fail results in a single fix that aggregates all mismatch locations.
|
||||
//
|
||||
// Types are not always resolved enough to enable that which means
|
||||
// that the comparison should be delayed, which brings us here - a
|
||||
// standalone constraint that represents such a match, in such cases
|
||||
// we create a fix per mismatch location and coalesce them during
|
||||
// diagnostics.
|
||||
if (flags.contains(TMF_MatchingGenericArguments))
|
||||
break;
|
||||
|
||||
Type fromType;
|
||||
Type toType;
|
||||
|
||||
if (path.size() >= 2) {
|
||||
if (path[path.size() - 2].is<LocatorPathElt::GenericType>()) {
|
||||
fromType = path[path.size() - 2]
|
||||
.castTo<LocatorPathElt::GenericType>()
|
||||
.getType();
|
||||
}
|
||||
|
||||
if (path[path.size() - 1].is<LocatorPathElt::GenericType>()) {
|
||||
toType = path[path.size() - 1]
|
||||
.castTo<LocatorPathElt::GenericType>()
|
||||
.getType();
|
||||
}
|
||||
}
|
||||
|
||||
if (!fromType || !toType)
|
||||
break;
|
||||
|
||||
// Drop both `GenericType` elements.
|
||||
path.pop_back();
|
||||
path.pop_back();
|
||||
|
||||
ConstraintFix *fix = nullptr;
|
||||
if (!path.empty() && path.back().is<LocatorPathElt::AnyRequirement>()) {
|
||||
fix = fixRequirementFailure(*this, fromType, toType, anchor, path);
|
||||
} else {
|
||||
fix = GenericArgumentsMismatch::create(
|
||||
*this, fromType, toType, {genericArgElt.getIndex()},
|
||||
getConstraintLocator(anchor, path));
|
||||
}
|
||||
|
||||
if (!fix)
|
||||
break;
|
||||
|
||||
conversionsOrFixes.push_back(fix);
|
||||
return true;
|
||||
}
|
||||
|
||||
case ConstraintLocator::ResultBuilderBodyResult: {
|
||||
@@ -7478,7 +7537,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
|
||||
// Attempt fixes iff it's allowed, both types are concrete and
|
||||
// we are not in the middle of attempting one already.
|
||||
if (shouldAttemptFixes() && !flags.contains(TMF_ApplyingFix)) {
|
||||
if (repairFailures(type1, type2, kind, conversionsOrFixes, locator)) {
|
||||
if (repairFailures(type1, type2, kind, flags, conversionsOrFixes,
|
||||
locator)) {
|
||||
if (conversionsOrFixes.empty())
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
@@ -14038,7 +14098,8 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
|
||||
case FixKind::MustBeCopyable:
|
||||
case FixKind::AllowInvalidPackElement:
|
||||
case FixKind::MacroMissingPound:
|
||||
case FixKind::AllowGlobalActorMismatch: {
|
||||
case FixKind::AllowGlobalActorMismatch:
|
||||
case FixKind::GenericArgumentsMismatch: {
|
||||
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
|
||||
}
|
||||
case FixKind::IgnoreInvalidASTNode: {
|
||||
@@ -14258,7 +14319,6 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
|
||||
case FixKind::TreatKeyPathSubscriptIndexAsHashable:
|
||||
case FixKind::AllowInvalidRefInKeyPath:
|
||||
case FixKind::DefaultGenericArgument:
|
||||
case FixKind::GenericArgumentsMismatch:
|
||||
case FixKind::AllowMutatingMemberOnRValueBase:
|
||||
case FixKind::AllowTupleSplatForSingleParameter:
|
||||
case FixKind::AllowNonClassTypeToConvertToAnyObject:
|
||||
|
||||
Reference in New Issue
Block a user