mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Diagnostics] Improve diagnostics related to pointer initialization
- Increase impact of a generic pointer-to-pointer mismatch fix to match that of a contextual type failure. This allows more specific fixes to take precedence. - De-prioritize generic argument mismatch fix when both types are pointers. This allows pointer-to-pointer conversion produce a more specific fix. - De-prioritize fixes that involve `Builtin.RawPointer` or `OpaquePointer` in parameter positions. This helps to produce better diagnostics for argument mismatches during pointer initialization e.g. `UnsafeRawPointer(<pointer>)`.
This commit is contained in:
@@ -2714,14 +2714,25 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2,
|
||||
}
|
||||
}
|
||||
|
||||
unsigned impact = 1;
|
||||
|
||||
if (type1->getAnyPointerElementType() &&
|
||||
type2->getAnyPointerElementType()) {
|
||||
// If this is a pointer <-> pointer conversion of different kind,
|
||||
// there is a dedicated restriction/fix for that in some cases.
|
||||
// To accommodate that, let's increase the impact of this fix.
|
||||
impact += 2;
|
||||
} else {
|
||||
// Increase the solution's score for each mismtach this fixes.
|
||||
impact += mismatches.size() - 1;
|
||||
}
|
||||
|
||||
auto *fix = GenericArgumentsMismatch::create(
|
||||
*this, type1, type2, mismatches, getConstraintLocator(locator));
|
||||
|
||||
if (!recordFix(fix)) {
|
||||
// Increase the solution's score for each mismtach this fixes.
|
||||
increaseScore(SK_Fix, mismatches.size() - 1);
|
||||
if (!recordFix(fix, impact))
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return matchDeepTypeArguments(*this, subflags, args1, args2, locator);
|
||||
@@ -10744,12 +10755,13 @@ ConstraintSystem::simplifyRestrictedConstraintImpl(
|
||||
auto *fix = GenericArgumentsMismatch::create(*this, ptr1, ptr2, {0},
|
||||
getConstraintLocator(locator));
|
||||
|
||||
// Treat this as a contextual type mismatch.
|
||||
unsigned baseImpact = 2;
|
||||
// It's possible to implicitly promote pointer into an optional
|
||||
// before matching base types if other side is an optional, so
|
||||
// score needs to account for number of such promotions.
|
||||
int optionalWraps = baseType2.getInt() - baseType1.getInt();
|
||||
return recordFix(fix,
|
||||
/*impact=*/1 + abs(optionalWraps))
|
||||
return recordFix(fix, baseImpact + abs(optionalWraps))
|
||||
? SolutionKind::Error
|
||||
: SolutionKind::Solved;
|
||||
};
|
||||
@@ -11553,6 +11565,23 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
|
||||
}
|
||||
}
|
||||
|
||||
// De-prioritize `Builtin.RawPointer` and `OpaquePointer` parameters
|
||||
// because they usually clash with generic parameter mismatches e.g.
|
||||
//
|
||||
// let ptr: UnsafePointer<String> = ...
|
||||
// _ = UnsafePointer<Int>(ups)
|
||||
//
|
||||
// Here initializer overloads have both `Builtin.RawPointer` and
|
||||
// `OpaquePointer` variants, but the actual issue is that generic argument
|
||||
// `String` doesn't match `Int`.
|
||||
{
|
||||
if (type2->is<BuiltinRawPointerType>())
|
||||
impact += 1;
|
||||
|
||||
if (type2->getAnyNominal() == getASTContext().getOpaquePointerDecl())
|
||||
impact += 1;
|
||||
}
|
||||
|
||||
return recordFix(fix, impact) ? SolutionKind::Error : SolutionKind::Solved;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user