@@ -336,6 +336,20 @@ namespace {
336
336
int toScalarIdx,
337
337
ConstraintLocatorBuilder locator);
338
338
339
+ // / \brief Coerce a subclass, class-constrained archetype, class-constrained
340
+ // / existential or to a superclass type.
341
+ // /
342
+ // / Also supports metatypes of the above.
343
+ // /
344
+ // / \param expr The expression to be coerced.
345
+ // / \param toType The type to which the expression will be coerced.
346
+ // / \param locator Locator describing where this conversion occurs.
347
+ // /
348
+ // / \return The coerced expression, whose type will be equivalent to
349
+ // / \c toType.
350
+ Expr *coerceSuperclass (Expr *expr, Type toType,
351
+ ConstraintLocatorBuilder locator);
352
+
339
353
// / \brief Coerce the given value to existential type.
340
354
// /
341
355
// / The following conversions are supported:
@@ -4590,6 +4604,79 @@ Expr *ExprRewriter::coerceScalarToTuple(Expr *expr, TupleType *toTuple,
4590
4604
destSugarTy));
4591
4605
}
4592
4606
4607
+ static Type getMetatypeSuperclass (Type t, TypeChecker &tc) {
4608
+ if (auto *metaTy = t->getAs <MetatypeType>())
4609
+ return MetatypeType::get (getMetatypeSuperclass (
4610
+ metaTy->getInstanceType (),
4611
+ tc));
4612
+
4613
+ if (auto *metaTy = t->getAs <ExistentialMetatypeType>())
4614
+ return ExistentialMetatypeType::get (getMetatypeSuperclass (
4615
+ metaTy->getInstanceType (),
4616
+ tc));
4617
+
4618
+ return tc.getSuperClassOf (t);
4619
+ }
4620
+
4621
+ Expr *ExprRewriter::coerceSuperclass (Expr *expr, Type toType,
4622
+ ConstraintLocatorBuilder locator) {
4623
+ auto &tc = cs.getTypeChecker ();
4624
+
4625
+ auto fromType = cs.getType (expr);
4626
+
4627
+ auto fromInstanceType = fromType;
4628
+ auto toInstanceType = toType;
4629
+
4630
+ while (fromInstanceType->is <AnyMetatypeType>() &&
4631
+ toInstanceType->is <MetatypeType>()) {
4632
+ fromInstanceType = fromInstanceType->castTo <AnyMetatypeType>()
4633
+ ->getInstanceType ();
4634
+ toInstanceType = toInstanceType->castTo <MetatypeType>()
4635
+ ->getInstanceType ();
4636
+ }
4637
+
4638
+ if (fromInstanceType->is <ArchetypeType>()) {
4639
+ // Coercion from archetype to its (concrete) superclass.
4640
+ auto superclass = getMetatypeSuperclass (fromType, tc);
4641
+
4642
+ expr =
4643
+ cs.cacheType (
4644
+ new (tc.Context ) ArchetypeToSuperExpr (expr, superclass));
4645
+
4646
+ if (!superclass->isEqual (toType))
4647
+ return coerceSuperclass (expr, toType, locator);
4648
+
4649
+ return expr;
4650
+
4651
+ }
4652
+
4653
+ if (fromInstanceType->isExistentialType ()) {
4654
+ // Coercion from superclass-constrained existential to its
4655
+ // concrete superclass.
4656
+ auto fromArchetype = ArchetypeType::getAnyOpened (fromType);
4657
+
4658
+ auto *archetypeVal =
4659
+ cs.cacheType (
4660
+ new (tc.Context ) OpaqueValueExpr (expr->getLoc (),
4661
+ fromArchetype));
4662
+
4663
+ auto *result = coerceSuperclass (archetypeVal, toType, locator);
4664
+
4665
+ return cs.cacheType (
4666
+ new (tc.Context ) OpenExistentialExpr (expr, archetypeVal, result,
4667
+ toType));
4668
+ }
4669
+
4670
+ // Coercion from subclass to superclass.
4671
+ if (toType->is <MetatypeType>()) {
4672
+ return cs.cacheType (
4673
+ new (tc.Context ) MetatypeConversionExpr (expr, toType));
4674
+ }
4675
+
4676
+ return cs.cacheType (
4677
+ new (tc.Context ) DerivedToBaseExpr (expr, toType));
4678
+ }
4679
+
4593
4680
// / Collect the conformances for all the protocols of an existential type.
4594
4681
// / If the source type is also existential, we don't want to check conformance
4595
4682
// / because most protocols do not conform to themselves -- however we still
@@ -5453,25 +5540,8 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
5453
5540
assert (toType->hasUnresolvedType () && " Should have handled this above" );
5454
5541
break ;
5455
5542
5456
- case ConversionRestrictionKind::Superclass: {
5457
- // Coercion from archetype to its (concrete) superclass.
5458
- if (auto fromArchetype = fromType->getAs <ArchetypeType>()) {
5459
- expr =
5460
- cs.cacheType (
5461
- new (tc.Context ) ArchetypeToSuperExpr (expr,
5462
- fromArchetype->getSuperclass ()));
5463
-
5464
- // If we are done succeeded, use the coerced result.
5465
- if (cs.getType (expr)->isEqual (toType)) {
5466
- return expr;
5467
- }
5468
-
5469
- fromType = cs.getType (expr);
5470
- }
5471
-
5472
- // Coercion from subclass to superclass.
5473
- return cs.cacheType (new (tc.Context ) DerivedToBaseExpr (expr, toType));
5474
- }
5543
+ case ConversionRestrictionKind::Superclass:
5544
+ return coerceSuperclass (expr, toType, locator);
5475
5545
5476
5546
case ConversionRestrictionKind::LValueToRValue: {
5477
5547
if (toType->is <TupleType>() || fromType->is <TupleType>())
@@ -5490,6 +5560,9 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
5490
5560
case ConversionRestrictionKind::MetatypeToExistentialMetatype:
5491
5561
return coerceExistential (expr, toType, locator);
5492
5562
5563
+ case ConversionRestrictionKind::ExistentialMetatypeToMetatype:
5564
+ return coerceSuperclass (expr, toType, locator);
5565
+
5493
5566
case ConversionRestrictionKind::ClassMetatypeToAnyObject: {
5494
5567
assert (tc.getLangOpts ().EnableObjCInterop
5495
5568
&& " metatypes can only be cast to objects w/ objc runtime!" );
@@ -5752,25 +5825,16 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
5752
5825
}
5753
5826
5754
5827
// Coercion from a subclass to a superclass.
5828
+ //
5829
+ // FIXME: Can we rig things up so that we always have a Superclass
5830
+ // conversion restriction in this case?
5755
5831
if (fromType->mayHaveSuperclass () &&
5756
5832
toType->getClassOrBoundGenericClass ()) {
5757
5833
for (auto fromSuperClass = tc.getSuperClassOf (fromType);
5758
5834
fromSuperClass;
5759
5835
fromSuperClass = tc.getSuperClassOf (fromSuperClass)) {
5760
5836
if (fromSuperClass->isEqual (toType)) {
5761
-
5762
- // Coercion from archetype to its (concrete) superclass.
5763
- if (auto fromArchetype = fromType->getAs <ArchetypeType>()) {
5764
- expr = cs.cacheType (new (tc.Context ) ArchetypeToSuperExpr (
5765
- expr, fromArchetype->getSuperclass ()));
5766
-
5767
- // If we succeeded, use the coerced result.
5768
- if (cs.getType (expr)->isEqual (toType))
5769
- return expr;
5770
- }
5771
-
5772
- // Coercion from subclass to superclass.
5773
- return cs.cacheType (new (tc.Context ) DerivedToBaseExpr (expr, toType));
5837
+ return coerceSuperclass (expr, toType, locator);
5774
5838
}
5775
5839
}
5776
5840
}
0 commit comments