@@ -6516,52 +6516,74 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
6516
6516
}
6517
6517
}
6518
6518
6519
+ // Handle "from specific" coercions before "catch all" coercions.
6520
+ auto desugaredFromType = fromType->getDesugaredType ();
6521
+ switch (desugaredFromType->getKind ()) {
6519
6522
// Coercions from an lvalue: load or perform implicit address-of. We perform
6520
6523
// these coercions first because they are often the first step in a multi-step
6521
6524
// 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 ) );
6534
6537
}
6535
6538
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);
6545
6549
}
6550
+ break ;
6546
6551
}
6547
6552
6553
+ case TypeKind::PrimaryArchetype:
6554
+ case TypeKind::OpenedArchetype:
6555
+ case TypeKind::NestedArchetype:
6556
+ if (!cast<ArchetypeType>(desugaredFromType)->requiresClass ())
6557
+ break ;
6558
+ LLVM_FALLTHROUGH;
6559
+
6548
6560
// Coercion from a subclass to a superclass.
6549
6561
//
6550
6562
// FIXME: Can we rig things up so that we always have a Superclass
6551
6563
// 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 ;
6554
6569
for (auto fromSuperClass = fromType->getSuperclass ();
6555
6570
fromSuperClass;
6556
6571
fromSuperClass = fromSuperClass->getSuperclass ()) {
6557
6572
if (fromSuperClass->isEqual (toType)) {
6558
6573
return coerceSuperclass (expr, toType, locator);
6559
6574
}
6560
6575
}
6576
+ break ;
6561
6577
}
6562
6578
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
+
6565
6587
// Default argument generator must return escaping functions. Therefore, we
6566
6588
// leave an explicit escape to noescape cast here such that SILGen can skip
6567
6589
// the cast and emit a code for the escaping function.
@@ -6570,49 +6592,52 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
6570
6592
isInDefaultArgumentContext = (initalizerCtx->getInitializerKind () ==
6571
6593
InitializerKind::DefaultArgument);
6572
6594
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));
6604
6616
}
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;
6605
6623
}
6624
+ }
6606
6625
6607
- maybeDiagnoseUnsupportedFunctionConversion (cs, expr, toFunc);
6626
+ maybeDiagnoseUnsupportedFunctionConversion (cs, expr, toFunc);
6608
6627
6609
- return cs.cacheType (new (tc.Context )
6610
- FunctionConversionExpr (expr, toType));
6611
- }
6628
+ return cs.cacheType (new (tc.Context )
6629
+ FunctionConversionExpr (expr, toType));
6612
6630
}
6613
6631
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);
6616
6641
if (toType->isAnyObject ()) {
6617
6642
assert (cs.getASTContext ().LangOpts .EnableObjCInterop
6618
6643
&& " metatype-to-object conversion requires objc interop" );
@@ -6648,39 +6673,46 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
6648
6673
new (tc.Context ) ProtocolMetatypeToObjectExpr (expr, toType));
6649
6674
}
6650
6675
}
6651
- }
6652
6676
6653
- // Coercions from a type to an existential type.
6654
- if (toType->isAnyExistentialType ()) {
6655
- return coerceExistential (expr, toType, locator);
6677
+ break ;
6656
6678
}
6657
6679
6658
- if (toType->getOptionalObjectType () &&
6659
- cs.getType (expr)->getOptionalObjectType ()) {
6660
- return coerceOptionalToOptional (expr, toType, locator, typeFromPattern);
6680
+ default :
6681
+ break ;
6661
6682
}
6662
6683
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
+
6663
6693
// 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 ());
6667
6699
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);
6671
6702
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
+ }
6677
6712
}
6678
6713
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 ;
6684
6716
}
6685
6717
6686
6718
// Unresolved types come up in diagnostics for lvalue and inout types.
0 commit comments