Skip to content

Commit 52aa243

Browse files
authored
Merge pull request #22681 from davezarzycki/coerceToType_switches
[Sema] NFC: refactor coerceToType() to use switch statments
2 parents 5b84670 + c037886 commit 52aa243

File tree

1 file changed

+117
-85
lines changed

1 file changed

+117
-85
lines changed

lib/Sema/CSApply.cpp

Lines changed: 117 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -6516,52 +6516,74 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
65166516
}
65176517
}
65186518

6519+
// Handle "from specific" coercions before "catch all" coercions.
6520+
auto desugaredFromType = fromType->getDesugaredType();
6521+
switch (desugaredFromType->getKind()) {
65196522
// Coercions from an lvalue: load or perform implicit address-of. We perform
65206523
// these coercions first because they are often the first step in a multi-step
65216524
// coercion.
6522-
if (auto fromLValue = fromType->getAs<LValueType>()) {
6523-
if (auto *toIO = toType->getAs<InOutType>()) {
6524-
// In an 'inout' operator like "i += 1", the operand is converted from
6525-
// an implicit lvalue to an inout argument.
6526-
assert(toIO->getObjectType()->isEqual(fromLValue->getObjectType()));
6527-
return cs.cacheType(new (tc.Context)
6528-
InOutExpr(expr->getStartLoc(), expr,
6529-
toIO->getObjectType(),
6530-
/*isImplicit*/ true));
6531-
}
6532-
6533-
return coerceToType(addImplicitLoadExpr(cs, expr), toType, locator);
6525+
case TypeKind::LValue: {
6526+
auto fromLValue = cast<LValueType>(desugaredFromType);
6527+
auto toIO = toType->getAs<InOutType>();
6528+
if (!toIO)
6529+
return coerceToType(addImplicitLoadExpr(cs, expr), toType, locator);
6530+
6531+
// In an 'inout' operator like "i += 1", the operand is converted from
6532+
// an implicit lvalue to an inout argument.
6533+
assert(toIO->getObjectType()->isEqual(fromLValue->getObjectType()));
6534+
return cs.cacheType(new (tc.Context) InOutExpr(expr->getStartLoc(), expr,
6535+
toIO->getObjectType(),
6536+
/*isImplicit*/ true));
65346537
}
65356538

6536-
// Coercions to tuple type.
6537-
if (auto toTuple = toType->getAs<TupleType>()) {
6538-
// Coerce from a tuple to a tuple.
6539-
if (auto fromTuple = fromType->getAs<TupleType>()) {
6540-
SmallVector<unsigned, 4> sources;
6541-
if (!computeTupleShuffle(fromTuple, toTuple, sources)) {
6542-
return coerceTupleToTuple(expr, fromTuple, toTuple,
6543-
locator, sources);
6544-
}
6539+
// Coerce from a tuple to a tuple.
6540+
case TypeKind::Tuple: {
6541+
auto fromTuple = cast<TupleType>(desugaredFromType);
6542+
auto toTuple = toType->getAs<TupleType>();
6543+
if (!toTuple)
6544+
break;
6545+
SmallVector<unsigned, 4> sources;
6546+
if (!computeTupleShuffle(fromTuple, toTuple, sources)) {
6547+
return coerceTupleToTuple(expr, fromTuple, toTuple,
6548+
locator, sources);
65456549
}
6550+
break;
65466551
}
65476552

6553+
case TypeKind::PrimaryArchetype:
6554+
case TypeKind::OpenedArchetype:
6555+
case TypeKind::NestedArchetype:
6556+
if (!cast<ArchetypeType>(desugaredFromType)->requiresClass())
6557+
break;
6558+
LLVM_FALLTHROUGH;
6559+
65486560
// Coercion from a subclass to a superclass.
65496561
//
65506562
// FIXME: Can we rig things up so that we always have a Superclass
65516563
// conversion restriction in this case?
6552-
if (fromType->mayHaveSuperclass() &&
6553-
toType->getClassOrBoundGenericClass()) {
6564+
case TypeKind::DynamicSelf:
6565+
case TypeKind::BoundGenericClass:
6566+
case TypeKind::Class: {
6567+
if (!toType->getClassOrBoundGenericClass())
6568+
break;
65546569
for (auto fromSuperClass = fromType->getSuperclass();
65556570
fromSuperClass;
65566571
fromSuperClass = fromSuperClass->getSuperclass()) {
65576572
if (fromSuperClass->isEqual(toType)) {
65586573
return coerceSuperclass(expr, toType, locator);
65596574
}
65606575
}
6576+
break;
65616577
}
65626578

6563-
// Coercions to function type.
6564-
if (auto toFunc = toType->getAs<FunctionType>()) {
6579+
// Coercion from one function type to another, this produces a
6580+
// FunctionConversionExpr in its full generality.
6581+
case TypeKind::Function: {
6582+
auto fromFunc = cast<FunctionType>(desugaredFromType);
6583+
auto toFunc = toType->getAs<FunctionType>();
6584+
if (!toFunc)
6585+
break;
6586+
65656587
// Default argument generator must return escaping functions. Therefore, we
65666588
// leave an explicit escape to noescape cast here such that SILGen can skip
65676589
// the cast and emit a code for the escaping function.
@@ -6570,49 +6592,52 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
65706592
isInDefaultArgumentContext = (initalizerCtx->getInitializerKind() ==
65716593
InitializerKind::DefaultArgument);
65726594
auto toEI = toFunc->getExtInfo();
6573-
// Coercion from one function type to another, this produces a
6574-
// FunctionConversionExpr in its full generality.
6575-
if (auto fromFunc = fromType->getAs<FunctionType>()) {
6576-
assert(toType->is<FunctionType>());
6577-
// If we have a ClosureExpr, then we can safely propagate the 'no escape'
6578-
// bit to the closure without invalidating prior analysis.
6579-
auto fromEI = fromFunc->getExtInfo();
6580-
if (toEI.isNoEscape() && !fromEI.isNoEscape()) {
6581-
auto newFromFuncType = fromFunc->withExtInfo(fromEI.withNoEscape());
6582-
if (!isInDefaultArgumentContext &&
6583-
applyTypeToClosureExpr(cs, expr, newFromFuncType)) {
6584-
fromFunc = newFromFuncType->castTo<FunctionType>();
6585-
// Propagating the 'no escape' bit might have satisfied the entire
6586-
// conversion. If so, we're done, otherwise keep converting.
6587-
if (fromFunc->isEqual(toType))
6588-
return expr;
6589-
} else if (isInDefaultArgumentContext) {
6590-
// First apply the conversion *without* noescape attribute.
6591-
if (!newFromFuncType->isEqual(toType)) {
6592-
auto escapingToFuncTy =
6593-
toFunc->withExtInfo(toEI.withNoEscape(false));
6594-
maybeDiagnoseUnsupportedFunctionConversion(cs, expr, toFunc);
6595-
expr = cs.cacheType(new (tc.Context) FunctionConversionExpr(
6596-
expr, escapingToFuncTy));
6597-
}
6598-
// Apply an explict function conversion *only* for the escape to
6599-
// noescape conversion. This conversion will be stripped by the
6600-
// default argument generator. (We can't return a @noescape function)
6601-
auto newExpr = cs.cacheType(new (tc.Context)
6602-
FunctionConversionExpr(expr, toFunc));
6603-
return newExpr;
6595+
assert(toType->is<FunctionType>());
6596+
// If we have a ClosureExpr, then we can safely propagate the 'no escape'
6597+
// bit to the closure without invalidating prior analysis.
6598+
auto fromEI = fromFunc->getExtInfo();
6599+
if (toEI.isNoEscape() && !fromEI.isNoEscape()) {
6600+
auto newFromFuncType = fromFunc->withExtInfo(fromEI.withNoEscape());
6601+
if (!isInDefaultArgumentContext &&
6602+
applyTypeToClosureExpr(cs, expr, newFromFuncType)) {
6603+
fromFunc = newFromFuncType->castTo<FunctionType>();
6604+
// Propagating the 'no escape' bit might have satisfied the entire
6605+
// conversion. If so, we're done, otherwise keep converting.
6606+
if (fromFunc->isEqual(toType))
6607+
return expr;
6608+
} else if (isInDefaultArgumentContext) {
6609+
// First apply the conversion *without* noescape attribute.
6610+
if (!newFromFuncType->isEqual(toType)) {
6611+
auto escapingToFuncTy =
6612+
toFunc->withExtInfo(toEI.withNoEscape(false));
6613+
maybeDiagnoseUnsupportedFunctionConversion(cs, expr, toFunc);
6614+
expr = cs.cacheType(new (tc.Context) FunctionConversionExpr(
6615+
expr, escapingToFuncTy));
66046616
}
6617+
// Apply an explict function conversion *only* for the escape to
6618+
// noescape conversion. This conversion will be stripped by the
6619+
// default argument generator. (We can't return a @noescape function)
6620+
auto newExpr = cs.cacheType(new (tc.Context)
6621+
FunctionConversionExpr(expr, toFunc));
6622+
return newExpr;
66056623
}
6624+
}
66066625

6607-
maybeDiagnoseUnsupportedFunctionConversion(cs, expr, toFunc);
6626+
maybeDiagnoseUnsupportedFunctionConversion(cs, expr, toFunc);
66086627

6609-
return cs.cacheType(new (tc.Context)
6610-
FunctionConversionExpr(expr, toType));
6611-
}
6628+
return cs.cacheType(new (tc.Context)
6629+
FunctionConversionExpr(expr, toType));
66126630
}
66136631

6614-
// Coercions from metadata to objects.
6615-
if (auto fromMeta = fromType->getAs<AnyMetatypeType>()) {
6632+
// Coercions from one metatype to another.
6633+
case TypeKind::Metatype: {
6634+
if (auto toMeta = toType->getAs<MetatypeType>())
6635+
return cs.cacheType(new(tc.Context) MetatypeConversionExpr(expr, toMeta));
6636+
LLVM_FALLTHROUGH;
6637+
}
6638+
// Coercions from metatype to objects.
6639+
case TypeKind::ExistentialMetatype: {
6640+
auto fromMeta = cast<AnyMetatypeType>(desugaredFromType);
66166641
if (toType->isAnyObject()) {
66176642
assert(cs.getASTContext().LangOpts.EnableObjCInterop
66186643
&& "metatype-to-object conversion requires objc interop");
@@ -6648,39 +6673,46 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
66486673
new (tc.Context) ProtocolMetatypeToObjectExpr(expr, toType));
66496674
}
66506675
}
6651-
}
66526676

6653-
// Coercions from a type to an existential type.
6654-
if (toType->isAnyExistentialType()) {
6655-
return coerceExistential(expr, toType, locator);
6677+
break;
66566678
}
66576679

6658-
if (toType->getOptionalObjectType() &&
6659-
cs.getType(expr)->getOptionalObjectType()) {
6660-
return coerceOptionalToOptional(expr, toType, locator, typeFromPattern);
6680+
default:
6681+
break;
66616682
}
66626683

6684+
// "Catch all" coercions.
6685+
auto desugaredToType = toType->getDesugaredType();
6686+
switch (desugaredToType->getKind()) {
6687+
// Coercions from a type to an existential type.
6688+
case TypeKind::ExistentialMetatype:
6689+
case TypeKind::ProtocolComposition:
6690+
case TypeKind::Protocol: {
6691+
return coerceExistential(expr, toType, locator);
6692+
66636693
// Coercion to Optional<T>.
6664-
if (auto toGenericType = toType->getAs<BoundGenericType>()) {
6665-
if (toGenericType->getDecl()->isOptionalDecl()) {
6666-
tc.requireOptionalIntrinsics(expr->getLoc());
6694+
case TypeKind::BoundGenericEnum: {
6695+
auto toGenericType = cast<BoundGenericEnumType>(desugaredToType);
6696+
if (!toGenericType->getDecl()->isOptionalDecl())
6697+
break;
6698+
tc.requireOptionalIntrinsics(expr->getLoc());
66676699

6668-
Type valueType = toGenericType->getGenericArgs()[0];
6669-
expr = coerceToType(expr, valueType, locator);
6670-
if (!expr) return nullptr;
6700+
if (cs.getType(expr)->getOptionalObjectType())
6701+
return coerceOptionalToOptional(expr, toType, locator, typeFromPattern);
66716702

6672-
auto *result =
6673-
cs.cacheType(new (tc.Context) InjectIntoOptionalExpr(expr, toType));
6674-
diagnoseOptionalInjection(result);
6675-
return result;
6676-
}
6703+
Type valueType = toGenericType->getGenericArgs()[0];
6704+
expr = coerceToType(expr, valueType, locator);
6705+
if (!expr) return nullptr;
6706+
6707+
auto *result =
6708+
cs.cacheType(new (tc.Context) InjectIntoOptionalExpr(expr, toType));
6709+
diagnoseOptionalInjection(result);
6710+
return result;
6711+
}
66776712
}
66786713

6679-
// Coercion from one metatype to another.
6680-
if (fromType->is<MetatypeType>() &&
6681-
toType->is<MetatypeType>()) {
6682-
auto toMeta = toType->castTo<MetatypeType>();
6683-
return cs.cacheType(new (tc.Context) MetatypeConversionExpr(expr, toMeta));
6714+
default:
6715+
break;
66846716
}
66856717

66866718
// Unresolved types come up in diagnostics for lvalue and inout types.

0 commit comments

Comments
 (0)