@@ -627,16 +627,15 @@ namespace {
627
627
// / A physical path component which projects out an opened archetype
628
628
// / from an existential.
629
629
class OpenOpaqueExistentialComponent : public PhysicalPathComponent {
630
- static LValueTypeData getOpenedArchetypeTypeData (CanArchetypeType type) {
631
- return {
632
- AbstractionPattern::getOpaque (), type,
633
- SILType::getPrimitiveObjectType (type)
634
- };
630
+ CanArchetypeType getOpenedArchetype () const {
631
+ return cast<ArchetypeType>(getSubstFormalType ());
635
632
}
636
633
public:
637
- OpenOpaqueExistentialComponent (CanArchetypeType openedArchetype)
638
- : PhysicalPathComponent(getOpenedArchetypeTypeData(openedArchetype),
639
- OpenOpaqueExistentialKind) {}
634
+ OpenOpaqueExistentialComponent (CanArchetypeType openedArchetype,
635
+ LValueTypeData typeData)
636
+ : PhysicalPathComponent(typeData, OpenOpaqueExistentialKind) {
637
+ assert (getOpenedArchetype () == openedArchetype);
638
+ }
640
639
641
640
ManagedValue offset (SILGenFunction &SGF, SILLocation loc, ManagedValue base,
642
641
AccessKind accessKind) && override {
@@ -665,8 +664,7 @@ namespace {
665
664
llvm_unreachable (" Bad existential representation for address-only type" );
666
665
}
667
666
668
- SGF.setArchetypeOpeningSite (cast<ArchetypeType>(getSubstFormalType ()),
669
- addr);
667
+ SGF.setArchetypeOpeningSite (getOpenedArchetype (), addr);
670
668
return ManagedValue::forLValue (addr);
671
669
}
672
670
@@ -675,21 +673,17 @@ namespace {
675
673
}
676
674
};
677
675
678
- // / A local path component for the payload of a class existential.
676
+ // / A local path component for the payload of a class or metatype existential.
679
677
// /
680
678
// / TODO: Could be physical if we had a way to project out the
681
679
// / payload.
682
- class OpenClassExistentialComponent : public LogicalPathComponent {
683
- static LValueTypeData getOpenedArchetypeTypeData (CanArchetypeType type) {
684
- return {
685
- AbstractionPattern::getOpaque (), type,
686
- SILType::getPrimitiveObjectType (type)
687
- };
688
- }
680
+ class OpenNonOpaqueExistentialComponent : public LogicalPathComponent {
681
+ CanArchetypeType OpenedArchetype;
689
682
public:
690
- OpenClassExistentialComponent (CanArchetypeType openedArchetype)
691
- : LogicalPathComponent(getOpenedArchetypeTypeData(openedArchetype),
692
- OpenClassExistentialKind) {}
683
+ OpenNonOpaqueExistentialComponent (CanArchetypeType openedArchetype,
684
+ LValueTypeData typeData)
685
+ : LogicalPathComponent(typeData, OpenNonOpaqueExistentialKind),
686
+ OpenedArchetype (openedArchetype) {}
693
687
694
688
AccessKind getBaseAccessKind (SILGenFunction &SGF,
695
689
AccessKind kind) const override {
@@ -712,15 +706,23 @@ namespace {
712
706
auto result = SGF.emitLoad (loc, base.getValue (), TL,
713
707
SGFContext (), IsNotTake);
714
708
715
- assert (refType.isExistentialType () &&
709
+ assert (refType.isAnyExistentialType () &&
716
710
" base for open existential component must be an existential" );
717
- assert (refType.getPreferredExistentialRepresentation (SGF.SGM .M )
718
- == ExistentialRepresentation::Class);
719
- auto ref = SGF.B .createOpenExistentialRef (
720
- loc, result, getTypeOfRValue ());
711
+ ManagedValue ref;
712
+ if (refType.is <ExistentialMetatypeType>()) {
713
+ assert (refType.getPreferredExistentialRepresentation (SGF.SGM .M )
714
+ == ExistentialRepresentation::Metatype);
715
+ ref = ManagedValue::forUnmanaged (
716
+ SGF.B .createOpenExistentialMetatype (loc,
717
+ result.getUnmanagedValue (),
718
+ getTypeOfRValue ()));
719
+ } else {
720
+ assert (refType.getPreferredExistentialRepresentation (SGF.SGM .M )
721
+ == ExistentialRepresentation::Class);
722
+ ref = SGF.B .createOpenExistentialRef (loc, result, getTypeOfRValue ());
723
+ }
721
724
722
- SGF.setArchetypeOpeningSite (cast<ArchetypeType>(getSubstFormalType ()),
723
- ref.getValue ());
725
+ SGF.setArchetypeOpeningSite (OpenedArchetype, ref.getValue ());
724
726
725
727
return RValue (SGF, loc, getSubstFormalType (), ref);
726
728
}
@@ -730,15 +732,24 @@ namespace {
730
732
auto payload = std::move (value).forwardAsSingleValue (SGF, loc);
731
733
732
734
SmallVector<ProtocolConformanceRef, 2 > conformances;
733
- for (auto proto : cast<ArchetypeType>( getSubstFormalType ()) ->getConformsTo ())
735
+ for (auto proto : OpenedArchetype ->getConformsTo ())
734
736
conformances.push_back (ProtocolConformanceRef (proto));
735
737
736
- auto ref = SGF.B .createInitExistentialRef (
737
- loc,
738
- base.getType ().getObjectType (),
739
- getSubstFormalType (),
740
- payload,
741
- SGF.getASTContext ().AllocateCopy (conformances));
738
+ SILValue ref;
739
+ if (base.getType ().is <ExistentialMetatypeType>()) {
740
+ ref = SGF.B .createInitExistentialMetatype (
741
+ loc,
742
+ payload,
743
+ base.getType ().getObjectType (),
744
+ SGF.getASTContext ().AllocateCopy (conformances));
745
+ } else {
746
+ ref = SGF.B .createInitExistentialRef (
747
+ loc,
748
+ base.getType ().getObjectType (),
749
+ getSubstFormalType (),
750
+ payload,
751
+ SGF.getASTContext ().AllocateCopy (conformances));
752
+ }
742
753
743
754
auto &TL = SGF.getTypeLowering (base.getType ());
744
755
SGF.emitSemanticStore (loc, ref,
@@ -748,13 +759,13 @@ namespace {
748
759
std::unique_ptr<LogicalPathComponent>
749
760
clone (SILGenFunction &SGF, SILLocation loc) const override {
750
761
LogicalPathComponent *clone =
751
- new OpenClassExistentialComponent (
752
- cast<ArchetypeType>(getSubstFormalType ()));
762
+ new OpenNonOpaqueExistentialComponent (OpenedArchetype, getTypeData ());
753
763
return std::unique_ptr<LogicalPathComponent>(clone);
754
764
}
755
765
756
766
void print (raw_ostream &OS) const override {
757
- OS << " OpenClassExistentialComponent(...)\n " ;
767
+ OS << " OpenNonOpaqueExistentialComponent(" << OpenedArchetype
768
+ << " , ...)\n " ;
758
769
}
759
770
};
760
771
@@ -2072,6 +2083,7 @@ LValue SILGenLValue::visitOpaqueValueExpr(OpaqueValueExpr *e,
2072
2083
lv = SGF.emitOpenExistentialLValue (
2073
2084
opened, std::move (lv),
2074
2085
CanArchetypeType (opened->getOpenedArchetype ()),
2086
+ e->getType ()->getLValueOrInOutObjectType ()->getCanonicalType (),
2075
2087
accessKind);
2076
2088
return lv;
2077
2089
}
@@ -2977,23 +2989,30 @@ LValue
2977
2989
SILGenFunction::emitOpenExistentialLValue (SILLocation loc,
2978
2990
LValue &&lv,
2979
2991
CanArchetypeType openedArchetype,
2992
+ CanType formalRValueType,
2980
2993
AccessKind accessKind) {
2994
+ assert (!formalRValueType->isLValueType ());
2995
+ LValueTypeData typeData = {
2996
+ AbstractionPattern::getOpaque (), formalRValueType,
2997
+ getLoweredType (formalRValueType).getObjectType ()
2998
+ };
2999
+
2981
3000
// Open up the existential.
2982
3001
auto rep = lv.getTypeOfRValue ()
2983
3002
.getPreferredExistentialRepresentation (SGM.M );
2984
3003
switch (rep) {
2985
3004
case ExistentialRepresentation::Opaque:
2986
3005
case ExistentialRepresentation::Boxed: {
2987
- lv.add <OpenOpaqueExistentialComponent>(openedArchetype);
3006
+ lv.add <OpenOpaqueExistentialComponent>(openedArchetype, typeData );
2988
3007
break ;
2989
3008
}
3009
+ case ExistentialRepresentation::Metatype:
2990
3010
case ExistentialRepresentation::Class: {
2991
- lv.add <OpenClassExistentialComponent >(openedArchetype);
3011
+ lv.add <OpenNonOpaqueExistentialComponent >(openedArchetype, typeData );
2992
3012
break ;
2993
3013
}
2994
- default :
2995
- llvm_unreachable (" Cannot perform lvalue access of "
2996
- " non-opaque, non-class existential" );
3014
+ case ExistentialRepresentation::None:
3015
+ llvm_unreachable (" cannot open non-existential" );
2997
3016
}
2998
3017
2999
3018
return std::move (lv);
0 commit comments