Sema: Remove unnecessary level of indentation in matchTypes()

This commit is contained in:
Slava Pestov
2025-10-28 22:36:03 -04:00
parent 2149731ec6
commit 5ba8b1b774

View File

@@ -8098,191 +8098,189 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
}
}
if (kind >= ConstraintKind::Conversion) {
// Pointer arguments can be converted from pointer-compatible types.
if (kind >= ConstraintKind::ArgumentConversion) {
// It is never legal to form an autoclosure that results in these
// implicit conversions to pointer types.
bool isAutoClosureArgument = locator.isForAutoclosureResult();
// Pointer arguments can be converted from pointer-compatible types.
if (kind >= ConstraintKind::ArgumentConversion) {
Type unwrappedType2 = type2;
bool type2IsOptional = false;
if (Type unwrapped = type2->getOptionalObjectType()) {
type2IsOptional = true;
unwrappedType2 = unwrapped;
}
PointerTypeKind pointerKind;
if (Type pointeeTy =
unwrappedType2->getAnyPointerElementType(pointerKind)) {
switch (pointerKind) {
case PTK_UnsafeRawPointer:
case PTK_UnsafeMutableRawPointer:
case PTK_UnsafePointer:
case PTK_UnsafeMutablePointer:
// UnsafeMutablePointer can be converted from an inout reference to a
// scalar or array.
if (auto inoutType1 = dyn_cast<InOutType>(desugar1)) {
Type unwrappedType2 = type2;
bool type2IsOptional = false;
if (Type unwrapped = type2->getOptionalObjectType()) {
type2IsOptional = true;
unwrappedType2 = unwrapped;
}
PointerTypeKind pointerKind;
if (Type pointeeTy =
unwrappedType2->getAnyPointerElementType(pointerKind)) {
switch (pointerKind) {
case PTK_UnsafeRawPointer:
case PTK_UnsafeMutableRawPointer:
case PTK_UnsafePointer:
case PTK_UnsafeMutablePointer:
// UnsafeMutablePointer can be converted from an inout reference to a
// scalar or array.
if (auto inoutType1 = dyn_cast<InOutType>(desugar1)) {
if (!isAutoClosureArgument) {
auto inoutBaseType = getFixedTypeRecursive(
inoutType1->getInOutObjectType(), /*wantRValue=*/true);
// Wait until the base type of `inout` is sufficiently resolved
// before making any assessments regarding conversions.
if (inoutBaseType->isTypeVariableOrMember())
return formUnsolvedResult();
auto baseIsArray = inoutBaseType->isArray();
if (baseIsArray)
conversionsOrFixes.push_back(
ConversionRestrictionKind::ArrayToPointer);
// Only try an inout-to-pointer conversion if we know it's not
// an array being converted to a raw pointer type. Such
// conversions can only use array-to-pointer.
if (!baseIsArray || !isRawPointerKind(pointerKind)) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::InoutToPointer);
// If regular inout-to-pointer conversion doesn't work,
// let's try C pointer conversion that has special semantics
// for imported declarations.
if (isArgumentOfImportedDecl(locator)) {
conversionsOrFixes.push_back(
baseIsArray ? ConversionRestrictionKind::ArrayToCPointer
: ConversionRestrictionKind::InoutToCPointer);
}
}
}
}
// Operators cannot use these implicit conversions.
if (kind == ConstraintKind::ArgumentConversion) {
// We can potentially convert from an UnsafeMutablePointer
// of a different type, if we're a void pointer.
Type unwrappedType1 = type1;
bool type1IsOptional = false;
if (Type unwrapped = type1->getOptionalObjectType()) {
type1IsOptional = true;
unwrappedType1 = unwrapped;
}
// Don't handle normal optional-related conversions here.
if (unwrappedType1->isEqual(unwrappedType2))
break;
PointerTypeKind type1PointerKind;
bool type1IsPointer{
unwrappedType1->getAnyPointerElementType(type1PointerKind)};
bool optionalityMatches = !type1IsOptional || type2IsOptional;
if (type1IsPointer && optionalityMatches) {
if (type1PointerKind == PTK_UnsafeMutablePointer) {
// Favor an UnsafeMutablePointer-to-UnsafeMutablePointer
// conversion.
if (type1PointerKind != pointerKind)
increaseScore(ScoreKind::SK_ValueToPointerConversion,
locator);
conversionsOrFixes.push_back(
ConversionRestrictionKind::PointerToPointer);
}
// UnsafeMutableRawPointer -> UnsafeRawPointer
else if (type1PointerKind == PTK_UnsafeMutableRawPointer &&
pointerKind == PTK_UnsafeRawPointer) {
if (type1PointerKind != pointerKind)
increaseScore(ScoreKind::SK_ValueToPointerConversion,
locator);
conversionsOrFixes.push_back(
ConversionRestrictionKind::PointerToPointer);
}
}
// UnsafePointer and UnsafeRawPointer can also be converted from an
// array or string value, or a UnsafePointer or
// AutoreleasingUnsafeMutablePointer.
if (pointerKind == PTK_UnsafePointer
|| pointerKind == PTK_UnsafeRawPointer) {
if (!isAutoClosureArgument) {
auto inoutBaseType = getFixedTypeRecursive(
inoutType1->getInOutObjectType(), /*wantRValue=*/true);
// Wait until the base type of `inout` is sufficiently resolved
// before making any assessments regarding conversions.
if (inoutBaseType->isTypeVariableOrMember())
return formUnsolvedResult();
auto baseIsArray = inoutBaseType->isArray();
if (baseIsArray)
if (type1->isArray()) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::ArrayToPointer);
// Only try an inout-to-pointer conversion if we know it's not
// an array being converted to a raw pointer type. Such
// conversions can only use array-to-pointer.
if (!baseIsArray || !isRawPointerKind(pointerKind)) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::InoutToPointer);
// If regular inout-to-pointer conversion doesn't work,
// If regular array-to-pointer conversion doesn't work,
// let's try C pointer conversion that has special semantics
// for imported declarations.
if (isArgumentOfImportedDecl(locator)) {
conversionsOrFixes.push_back(
baseIsArray ? ConversionRestrictionKind::ArrayToCPointer
: ConversionRestrictionKind::InoutToCPointer);
ConversionRestrictionKind::ArrayToCPointer);
}
}
}
}
// Operators cannot use these implicit conversions.
if (kind == ConstraintKind::ArgumentConversion) {
// We can potentially convert from an UnsafeMutablePointer
// of a different type, if we're a void pointer.
Type unwrappedType1 = type1;
bool type1IsOptional = false;
if (Type unwrapped = type1->getOptionalObjectType()) {
type1IsOptional = true;
unwrappedType1 = unwrapped;
}
// The pointer can be converted from a string, if the element
// type is compatible.
auto &ctx = getASTContext();
if (type1->isString()) {
auto baseTy = getFixedTypeRecursive(pointeeTy, false);
// Don't handle normal optional-related conversions here.
if (unwrappedType1->isEqual(unwrappedType2))
break;
PointerTypeKind type1PointerKind;
bool type1IsPointer{
unwrappedType1->getAnyPointerElementType(type1PointerKind)};
bool optionalityMatches = !type1IsOptional || type2IsOptional;
if (type1IsPointer && optionalityMatches) {
if (type1PointerKind == PTK_UnsafeMutablePointer) {
// Favor an UnsafeMutablePointer-to-UnsafeMutablePointer
// conversion.
if (type1PointerKind != pointerKind)
increaseScore(ScoreKind::SK_ValueToPointerConversion,
locator);
conversionsOrFixes.push_back(
ConversionRestrictionKind::PointerToPointer);
}
// UnsafeMutableRawPointer -> UnsafeRawPointer
else if (type1PointerKind == PTK_UnsafeMutableRawPointer &&
pointerKind == PTK_UnsafeRawPointer) {
if (type1PointerKind != pointerKind)
increaseScore(ScoreKind::SK_ValueToPointerConversion,
locator);
conversionsOrFixes.push_back(
ConversionRestrictionKind::PointerToPointer);
}
}
// UnsafePointer and UnsafeRawPointer can also be converted from an
// array or string value, or a UnsafePointer or
// AutoreleasingUnsafeMutablePointer.
if (pointerKind == PTK_UnsafePointer
|| pointerKind == PTK_UnsafeRawPointer) {
if (!isAutoClosureArgument) {
if (type1->isArray()) {
if (baseTy->isTypeVariableOrMember() ||
isStringCompatiblePointerBaseType(ctx, baseTy))
conversionsOrFixes.push_back(
ConversionRestrictionKind::ArrayToPointer);
// If regular array-to-pointer conversion doesn't work,
// let's try C pointer conversion that has special semantics
// for imported declarations.
if (isArgumentOfImportedDecl(locator)) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::ArrayToCPointer);
}
}
// The pointer can be converted from a string, if the element
// type is compatible.
auto &ctx = getASTContext();
if (type1->isString()) {
auto baseTy = getFixedTypeRecursive(pointeeTy, false);
if (baseTy->isTypeVariableOrMember() ||
isStringCompatiblePointerBaseType(ctx, baseTy))
conversionsOrFixes.push_back(
ConversionRestrictionKind::StringToPointer);
}
}
if (type1IsPointer && optionalityMatches &&
(type1PointerKind == PTK_UnsafePointer ||
type1PointerKind == PTK_AutoreleasingUnsafeMutablePointer)) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::PointerToPointer);
ConversionRestrictionKind::StringToPointer);
}
}
// If both sides are non-optional pointers, let's check whether
// this argument supports Swift -> C pointer conversions.
//
// Do some light verification before recording restriction to
// avoid allocating constraints for obviously invalid cases.
if (type1IsPointer && !type1IsOptional && !type2IsOptional &&
(shouldAttemptFixes() || isArgumentOfImportedDecl(locator))) {
// UnsafeRawPointer -> UnsafePointer<[U]Int8>
if (type1PointerKind == PTK_UnsafeRawPointer &&
pointerKind == PTK_UnsafePointer) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::PointerToCPointer);
}
// UnsafeMutableRawPointer -> Unsafe[Mutable]Pointer<[U]Int8>
if (type1PointerKind == PTK_UnsafeMutableRawPointer &&
(pointerKind == PTK_UnsafePointer ||
pointerKind == PTK_UnsafeMutablePointer)) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::PointerToCPointer);
}
// Unsafe[Mutable]Pointer -> Unsafe[Mutable]Pointer
if (type1PointerKind == PTK_UnsafePointer &&
pointerKind == PTK_UnsafePointer) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::PointerToCPointer);
}
if (type1PointerKind == PTK_UnsafeMutablePointer &&
(pointerKind == PTK_UnsafePointer ||
pointerKind == PTK_UnsafeMutablePointer)) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::PointerToCPointer);
}
if (type1IsPointer && optionalityMatches &&
(type1PointerKind == PTK_UnsafePointer ||
type1PointerKind == PTK_AutoreleasingUnsafeMutablePointer)) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::PointerToPointer);
}
}
break;
case PTK_AutoreleasingUnsafeMutablePointer:
// PTK_AutoreleasingUnsafeMutablePointer can be converted from an
// inout reference to a scalar.
if (!isAutoClosureArgument && type1->is<InOutType>()) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::InoutToPointer);
// If both sides are non-optional pointers, let's check whether
// this argument supports Swift -> C pointer conversions.
//
// Do some light verification before recording restriction to
// avoid allocating constraints for obviously invalid cases.
if (type1IsPointer && !type1IsOptional && !type2IsOptional &&
(shouldAttemptFixes() || isArgumentOfImportedDecl(locator))) {
// UnsafeRawPointer -> UnsafePointer<[U]Int8>
if (type1PointerKind == PTK_UnsafeRawPointer &&
pointerKind == PTK_UnsafePointer) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::PointerToCPointer);
}
// UnsafeMutableRawPointer -> Unsafe[Mutable]Pointer<[U]Int8>
if (type1PointerKind == PTK_UnsafeMutableRawPointer &&
(pointerKind == PTK_UnsafePointer ||
pointerKind == PTK_UnsafeMutablePointer)) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::PointerToCPointer);
}
// Unsafe[Mutable]Pointer -> Unsafe[Mutable]Pointer
if (type1PointerKind == PTK_UnsafePointer &&
pointerKind == PTK_UnsafePointer) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::PointerToCPointer);
}
if (type1PointerKind == PTK_UnsafeMutablePointer &&
(pointerKind == PTK_UnsafePointer ||
pointerKind == PTK_UnsafeMutablePointer)) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::PointerToCPointer);
}
}
break;
}
break;
case PTK_AutoreleasingUnsafeMutablePointer:
// PTK_AutoreleasingUnsafeMutablePointer can be converted from an
// inout reference to a scalar.
if (!isAutoClosureArgument && type1->is<InOutType>()) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::InoutToPointer);
}
break;
}
}
}