Skip to content

Commit 185e6fa

Browse files
committed
Add TypeBase::isArrayType helper API.
This is also needed in SIL diagnostics, not just Sema diagnostics, because implicit Array conversion generates special SIL patterns.
1 parent c94210c commit 185e6fa

File tree

12 files changed

+58
-66
lines changed

12 files changed

+58
-66
lines changed

include/swift/AST/Types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,10 @@ class alignas(1 << TypeAlignInBits) TypeBase
831831
/// type) from `DistributedActor`.
832832
bool isDistributedActor();
833833

834+
/// Determine if the type in question is an Array<T> and, if so, provide the
835+
/// element type of the array.
836+
Type isArrayType();
837+
834838
/// Determines the element type of a known
835839
/// [Autoreleasing]Unsafe[Mutable][Raw]Pointer variant, or returns null if the
836840
/// type is not a pointer.

include/swift/Sema/ConstraintSystem.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4731,10 +4731,6 @@ class ConstraintSystem {
47314731
bool updateState = true,
47324732
bool notifyBindingInference = true);
47334733

4734-
/// Determine if the type in question is an Array<T> and, if so, provide the
4735-
/// element type of the array.
4736-
static Optional<Type> isArrayType(Type type);
4737-
47384734
/// Determine whether the given type is a dictionary and, if so, provide the
47394735
/// key and value types for the dictionary.
47404736
static Optional<std::pair<Type, Type>> isDictionaryType(Type type);

lib/AST/Type.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,14 @@ CanType CanType::wrapInOptionalTypeImpl(CanType type) {
823823
return type->wrapInOptionalType()->getCanonicalType();
824824
}
825825

826+
Type TypeBase::isArrayType() {
827+
if (auto boundStruct = getAs<BoundGenericStructType>()) {
828+
if (boundStruct->getDecl() == getASTContext().getArrayDecl())
829+
return boundStruct->getGenericArgs()[0];
830+
}
831+
return Type();
832+
}
833+
826834
Type TypeBase::getAnyPointerElementType(PointerTypeKind &PTK) {
827835
auto &C = getASTContext();
828836
if (isUnsafeMutableRawPointer()) {

lib/Sema/CSApply.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6453,8 +6453,8 @@ bool ExprRewriter::peepholeCollectionUpcast(Expr *expr, Type toType,
64536453

64546454
// Array literals.
64556455
if (auto arrayLiteral = dyn_cast<ArrayExpr>(expr)) {
6456-
if (Optional<Type> elementType = ConstraintSystem::isArrayType(toType)) {
6457-
peepholeArrayUpcast(arrayLiteral, toType, bridged, *elementType, locator);
6456+
if (Type elementType = toType->isArrayType()) {
6457+
peepholeArrayUpcast(arrayLiteral, toType, bridged, elementType, locator);
64586458
return true;
64596459
}
64606460

@@ -6498,8 +6498,7 @@ Expr *ExprRewriter::buildCollectionUpcastExpr(
64986498
bridged, locator, 0);
64996499

65006500
// For single-parameter collections, form the upcast.
6501-
if (ConstraintSystem::isArrayType(toType) ||
6502-
ConstraintSystem::isSetType(toType)) {
6501+
if (toType->isArrayType() || ConstraintSystem::isSetType(toType)) {
65036502
return cs.cacheType(
65046503
new (ctx) CollectionUpcastConversionExpr(expr, toType, {}, conv));
65056504
}
@@ -6524,12 +6523,11 @@ Expr *ExprRewriter::buildObjCBridgeExpr(Expr *expr, Type toType,
65246523

65256524
// Bridged collection casts always succeed, so we treat them as
65266525
// collection "upcasts".
6527-
if ((ConstraintSystem::isArrayType(fromType) &&
6528-
ConstraintSystem::isArrayType(toType)) ||
6529-
(ConstraintSystem::isDictionaryType(fromType) &&
6530-
ConstraintSystem::isDictionaryType(toType)) ||
6531-
(ConstraintSystem::isSetType(fromType) &&
6532-
ConstraintSystem::isSetType(toType))) {
6526+
if ((fromType->isArrayType() && toType->isArrayType())
6527+
|| (ConstraintSystem::isDictionaryType(fromType)
6528+
&& ConstraintSystem::isDictionaryType(toType))
6529+
|| (ConstraintSystem::isSetType(fromType)
6530+
&& ConstraintSystem::isSetType(toType))) {
65336531
return buildCollectionUpcastExpr(expr, toType, /*bridged=*/true, locator);
65346532
}
65356533

lib/Sema/CSDiagnostics.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,8 +1746,8 @@ bool RValueTreatedAsLValueFailure::diagnoseAsError() {
17461746
auto argType = getType(inoutExpr)->getWithoutSpecifierType();
17471747

17481748
PointerTypeKind ptr;
1749-
if (isArrayType(argType) && paramType->getAnyPointerElementType(ptr) &&
1750-
(ptr == PTK_UnsafePointer || ptr == PTK_UnsafeRawPointer)) {
1749+
if (argType->isArrayType() && paramType->getAnyPointerElementType(ptr)
1750+
&& (ptr == PTK_UnsafePointer || ptr == PTK_UnsafeRawPointer)) {
17511751
emitDiagnosticAt(inoutExpr->getLoc(),
17521752
diag::extra_address_of_unsafepointer, paramType)
17531753
.highlight(inoutExpr->getSourceRange())

lib/Sema/CSDiagnostics.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,11 +224,6 @@ class FailureDiagnostic {
224224
llvm::function_ref<void(GenericTypeParamType *, Type)> substitution =
225225
[](GenericTypeParamType *, Type) {});
226226

227-
bool isArrayType(Type type) const {
228-
auto &cs = getConstraintSystem();
229-
return bool(cs.isArrayType(type));
230-
}
231-
232227
bool conformsToKnownProtocol(Type type, KnownProtocolKind protocol) const;
233228
};
234229

lib/Sema/CSFix.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ TreatArrayLiteralAsDictionary *
193193
TreatArrayLiteralAsDictionary::attempt(ConstraintSystem &cs, Type dictionaryTy,
194194
Type arrayTy,
195195
ConstraintLocator *locator) {
196-
if (!cs.isArrayType(arrayTy))
196+
if (!arrayTy->isArrayType())
197197
return nullptr;
198198

199199
// Determine the ArrayExpr from the locator.
@@ -1676,15 +1676,15 @@ ExpandArrayIntoVarargs::attempt(ConstraintSystem &cs, Type argType,
16761676
if (!(argLoc && argLoc->getParameterFlags().isVariadic()))
16771677
return nullptr;
16781678

1679-
auto elementType = cs.isArrayType(argType);
1679+
auto elementType = argType->isArrayType();
16801680
if (!elementType)
16811681
return nullptr;
16821682

16831683
ConstraintSystem::TypeMatchOptions options;
16841684
options |= ConstraintSystem::TypeMatchFlags::TMF_ApplyingFix;
16851685
options |= ConstraintSystem::TypeMatchFlags::TMF_GenerateConstraints;
16861686

1687-
auto result = cs.matchTypes(*elementType, paramType, ConstraintKind::Subtype,
1687+
auto result = cs.matchTypes(elementType, paramType, ConstraintKind::Subtype,
16881688
options, builder);
16891689

16901690
if (result.isFailure())

lib/Sema/CSGen.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -981,8 +981,8 @@ namespace {
981981
isLValueBase = true;
982982
baseObjTy = baseObjTy->getWithoutSpecifierType();
983983
}
984-
985-
if (CS.isArrayType(baseObjTy.getPointer())) {
984+
985+
if (baseObjTy->isArrayType()) {
986986

987987
if (auto arraySliceTy =
988988
dyn_cast<ArraySliceType>(baseObjTy.getPointer())) {
@@ -1981,14 +1981,13 @@ namespace {
19811981
};
19821982

19831983
// If a contextual type exists for this expression, apply it directly.
1984-
if (contextualType && ConstraintSystem::isArrayType(contextualType)) {
1984+
if (contextualType && contextualType->isArrayType()) {
19851985
// Now that we know we're actually going to use the type, get the
19861986
// version for use in a constraint.
19871987
contextualType = CS.getContextualType(expr, /*forConstraint=*/true);
19881988
contextualType = CS.openOpaqueType(
19891989
contextualType, contextualPurpose, locator);
1990-
Optional<Type> arrayElementType =
1991-
ConstraintSystem::isArrayType(contextualType);
1990+
Type arrayElementType = contextualType->isArrayType();
19921991
CS.addConstraint(ConstraintKind::LiteralConformsTo, contextualType,
19931992
arrayProto->getDeclaredInterfaceType(),
19941993
locator);

lib/Sema/CSSimplify.cpp

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5585,8 +5585,8 @@ bool ConstraintSystem::repairFailures(
55855585
// ```
55865586
if (rhs->isKnownStdlibCollectionType()) {
55875587
std::function<Type(Type)> getArrayOrSetType = [&](Type type) -> Type {
5588-
if (auto eltTy = isArrayType(type))
5589-
return getArrayOrSetType(*eltTy);
5588+
if (auto eltTy = type->isArrayType())
5589+
return getArrayOrSetType(eltTy);
55905590

55915591
if (auto eltTy = isSetType(type))
55925592
return getArrayOrSetType(*eltTy);
@@ -7194,7 +7194,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
71947194
// Special implicit nominal conversions.
71957195
if (!type1->is<LValueType>() && kind >= ConstraintKind::Subtype) {
71967196
// Array -> Array.
7197-
if (isArrayType(desugar1) && isArrayType(desugar2)) {
7197+
if (desugar1->isArrayType() && desugar2->isArrayType()) {
71987198
conversionsOrFixes.push_back(ConversionRestrictionKind::ArrayUpcast);
71997199
// Dictionary -> Dictionary.
72007200
} else if (isDictionaryType(desugar1) && isDictionaryType(desugar2)) {
@@ -7240,8 +7240,9 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
72407240
if (!isAutoClosureArgument) {
72417241
auto inoutBaseType = inoutType1->getInOutObjectType();
72427242

7243-
auto baseIsArray = isArrayType(
7244-
getFixedTypeRecursive(inoutBaseType, /*wantRValue=*/true));
7243+
auto baseIsArray =
7244+
getFixedTypeRecursive(inoutBaseType, /*wantRValue=*/true)
7245+
->isArrayType();
72457246

72467247
// FIXME: If the base is still a type variable, we can't tell
72477248
// what to do here. Might have to try \c ArrayToPointer and make
@@ -7311,7 +7312,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
73117312
if (pointerKind == PTK_UnsafePointer
73127313
|| pointerKind == PTK_UnsafeRawPointer) {
73137314
if (!isAutoClosureArgument) {
7314-
if (isArrayType(type1)) {
7315+
if (type1->isArrayType()) {
73157316
conversionsOrFixes.push_back(
73167317
ConversionRestrictionKind::ArrayToPointer);
73177318
}
@@ -8295,9 +8296,9 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyTransitivelyConformsTo(
82958296
}
82968297

82978298
// Array<T> -> Unsafe{Raw}Pointer<T>
8298-
if (auto elt = isArrayType(resolvedTy)) {
8299-
typesToCheck.push_back(getPointerFor(PTK_UnsafePointer, *elt));
8300-
typesToCheck.push_back(getPointerFor(PTK_UnsafeRawPointer, *elt));
8299+
if (auto elt = resolvedTy->isArrayType()) {
8300+
typesToCheck.push_back(getPointerFor(PTK_UnsafePointer, elt));
8301+
typesToCheck.push_back(getPointerFor(PTK_UnsafeRawPointer, elt));
83018302
}
83028303

83038304
// inout argument -> UnsafePointer<T>, UnsafeMutablePointer<T>,
@@ -8327,7 +8328,7 @@ static CheckedCastKind getCheckedCastKind(ConstraintSystem *cs,
83278328
Type fromType,
83288329
Type toType) {
83298330
// Array downcasts are handled specially.
8330-
if (cs->isArrayType(fromType) && cs->isArrayType(toType)) {
8331+
if (fromType->isArrayType() && toType->isArrayType()) {
83318332
return CheckedCastKind::ArrayDowncast;
83328333
}
83338334

@@ -8577,9 +8578,9 @@ ConstraintSystem::simplifyCheckedCastConstraint(
85778578
auto kind = getCheckedCastKind(this, fromType, toType);
85788579
switch (kind) {
85798580
case CheckedCastKind::ArrayDowncast: {
8580-
auto fromBaseType = *isArrayType(fromType);
8581-
auto toBaseType = *isArrayType(toType);
8582-
8581+
auto fromBaseType = fromType->isArrayType();
8582+
auto toBaseType = toType->isArrayType();
8583+
85838584
auto elementLocator =
85848585
locator.withPathElement(LocatorPathElt::GenericArgument(0));
85858586
auto result = simplifyCheckedCastConstraint(fromBaseType, toBaseType,
@@ -11253,11 +11254,11 @@ ConstraintSystem::simplifyBridgingConstraint(Type type1,
1125311254
};
1125411255

1125511256
// Bridging the elements of an array.
11256-
if (auto fromElement = isArrayType(unwrappedFromType)) {
11257-
if (auto toElement = isArrayType(unwrappedToType)) {
11257+
if (auto fromElement = unwrappedFromType->isArrayType()) {
11258+
if (auto toElement = unwrappedToType->isArrayType()) {
1125811259
countOptionalInjections();
1125911260
auto result = simplifyBridgingConstraint(
11260-
*fromElement, *toElement, subflags,
11261+
fromElement, toElement, subflags,
1126111262
locator.withPathElement(LocatorPathElt::GenericArgument(0)));
1126211263
return makeCollectionResult(result);
1126311264
}
@@ -13252,7 +13253,7 @@ ConstraintSystem::simplifyRestrictedConstraintImpl(
1325213253

1325313254
auto t2 = type2->getDesugaredType();
1325413255

13255-
auto baseType1 = getFixedTypeRecursive(*isArrayType(obj1), false);
13256+
auto baseType1 = getFixedTypeRecursive(obj1->isArrayType(), false);
1325613257
auto ptr2 = getBaseTypeForPointer(t2);
1325713258

1325813259
increaseScore(SK_ValueToOptional, ptr2.getInt());
@@ -13366,8 +13367,8 @@ ConstraintSystem::simplifyRestrictedConstraintImpl(
1336613367

1336713368
// T < U or T is bridged to V where V < U ===> Array<T> <c Array<U>
1336813369
case ConversionRestrictionKind::ArrayUpcast: {
13369-
Type baseType1 = *isArrayType(type1);
13370-
Type baseType2 = *isArrayType(type2);
13370+
Type baseType1 = type1->isArrayType();
13371+
Type baseType2 = type2->isArrayType();
1337113372

1337213373
increaseScore(SK_CollectionUpcastConversion);
1337313374
return matchTypes(baseType1,
@@ -14126,13 +14127,13 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1412614127
auto dictionaryKeyTy = DependentMemberType::get(valueBaseTy, keyAssocTy);
1412714128

1412814129
// Extract the array element type.
14129-
auto elemTy = isArrayType(type1);
14130+
auto elemTy = type1->isArrayType();
1413014131

1413114132
ConstraintLocator *elemLoc = getConstraintLocator(AE->getElement(0));
1413214133
ConstraintKind kind = isDictionaryType(dictTy)
1413314134
? ConstraintKind::Conversion
1413414135
: ConstraintKind::Equal;
14135-
return matchTypes(*elemTy, dictionaryKeyTy, kind, subflags, elemLoc);
14136+
return matchTypes(elemTy, dictionaryKeyTy, kind, subflags, elemLoc);
1413614137
}
1413714138

1413814139
case FixKind::ContextualMismatch:

lib/Sema/ConstraintSystem.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,15 +1071,6 @@ FunctionType *ConstraintSystem::openFunctionType(
10711071
return funcType->castTo<FunctionType>();
10721072
}
10731073

1074-
Optional<Type> ConstraintSystem::isArrayType(Type type) {
1075-
if (auto boundStruct = type->getAs<BoundGenericStructType>()) {
1076-
if (boundStruct->getDecl() == type->getASTContext().getArrayDecl())
1077-
return boundStruct->getGenericArgs()[0];
1078-
}
1079-
1080-
return None;
1081-
}
1082-
10831074
Optional<std::pair<Type, Type>> ConstraintSystem::isDictionaryType(Type type) {
10841075
if (auto boundStruct = type->getAs<BoundGenericStructType>()) {
10851076
if (boundStruct->getDecl() == type->getASTContext().getDictionaryDecl()) {

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1799,9 +1799,9 @@ TypeChecker::typeCheckCheckedCast(Type fromType, Type toType,
17991799
};
18001800

18011801
// Check for casts between specific concrete types that cannot succeed.
1802-
if (auto toElementType = ConstraintSystem::isArrayType(toType)) {
1803-
if (auto fromElementType = ConstraintSystem::isArrayType(fromType)) {
1804-
return checkElementCast(*fromElementType, *toElementType,
1802+
if (auto toElementType = toType->isArrayType()) {
1803+
if (auto fromElementType = fromType->isArrayType()) {
1804+
return checkElementCast(fromElementType, toElementType,
18051805
CheckedCastKind::ArrayDowncast);
18061806
}
18071807
}

unittests/Sema/PlaceholderTypeInferenceTests.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ TEST_F(SemaTest, TestPlaceholderInferenceForArrayLiteral) {
4747

4848
auto &solution = solutions[0];
4949

50-
auto eltTy = ConstraintSystem::isArrayType(solution.simplifyType(solution.getType(arrayExpr)));
51-
ASSERT_TRUE(eltTy.has_value());
52-
ASSERT_TRUE((*eltTy)->is<StructType>());
53-
ASSERT_EQ((*eltTy)->getAs<StructType>()->getDecl(), intTypeDecl);
50+
auto eltTy = solution.simplifyType(solution.getType(arrayExpr))->isArrayType();
51+
ASSERT_TRUE(eltTy);
52+
ASSERT_TRUE(eltTy->is<StructType>());
53+
ASSERT_EQ(eltTy->getAs<StructType>()->getDecl(), intTypeDecl);
5454
}
5555

5656
TEST_F(SemaTest, TestPlaceholderInferenceForDictionaryLiteral) {

0 commit comments

Comments
 (0)