@@ -631,16 +631,15 @@ namespace {
631
631
// / A physical path component which projects out an opened archetype
632
632
// / from an existential.
633
633
class OpenOpaqueExistentialComponent : public PhysicalPathComponent {
634
- static LValueTypeData getOpenedArchetypeTypeData (CanArchetypeType type) {
635
- return {
636
- AbstractionPattern::getOpaque (), type,
637
- SILType::getPrimitiveObjectType (type)
638
- };
634
+ CanArchetypeType getOpenedArchetype () const {
635
+ return cast<ArchetypeType>(getSubstFormalType ());
639
636
}
640
637
public:
641
- OpenOpaqueExistentialComponent (CanArchetypeType openedArchetype)
642
- : PhysicalPathComponent(getOpenedArchetypeTypeData(openedArchetype),
643
- OpenOpaqueExistentialKind) {}
638
+ OpenOpaqueExistentialComponent (CanArchetypeType openedArchetype,
639
+ LValueTypeData typeData)
640
+ : PhysicalPathComponent(typeData, OpenOpaqueExistentialKind) {
641
+ assert (getOpenedArchetype () == openedArchetype);
642
+ }
644
643
645
644
ManagedValue offset (SILGenFunction &SGF, SILLocation loc, ManagedValue base,
646
645
AccessKind accessKind) && override {
@@ -669,8 +668,7 @@ namespace {
669
668
llvm_unreachable (" Bad existential representation for address-only type" );
670
669
}
671
670
672
- SGF.setArchetypeOpeningSite (cast<ArchetypeType>(getSubstFormalType ()),
673
- addr);
671
+ SGF.setArchetypeOpeningSite (getOpenedArchetype (), addr);
674
672
return ManagedValue::forLValue (addr);
675
673
}
676
674
@@ -679,21 +677,17 @@ namespace {
679
677
}
680
678
};
681
679
682
- // / A local path component for the payload of a class existential.
680
+ // / A local path component for the payload of a class or metatype existential.
683
681
// /
684
682
// / TODO: Could be physical if we had a way to project out the
685
683
// / payload.
686
- class OpenClassExistentialComponent : public LogicalPathComponent {
687
- static LValueTypeData getOpenedArchetypeTypeData (CanArchetypeType type) {
688
- return {
689
- AbstractionPattern::getOpaque (), type,
690
- SILType::getPrimitiveObjectType (type)
691
- };
692
- }
684
+ class OpenNonOpaqueExistentialComponent : public LogicalPathComponent {
685
+ CanArchetypeType OpenedArchetype;
693
686
public:
694
- OpenClassExistentialComponent (CanArchetypeType openedArchetype)
695
- : LogicalPathComponent(getOpenedArchetypeTypeData(openedArchetype),
696
- OpenClassExistentialKind) {}
687
+ OpenNonOpaqueExistentialComponent (CanArchetypeType openedArchetype,
688
+ LValueTypeData typeData)
689
+ : LogicalPathComponent(typeData, OpenNonOpaqueExistentialKind),
690
+ OpenedArchetype (openedArchetype) {}
697
691
698
692
AccessKind getBaseAccessKind (SILGenFunction &SGF,
699
693
AccessKind kind) const override {
@@ -716,15 +710,23 @@ namespace {
716
710
auto result = SGF.emitLoad (loc, base.getValue (), TL,
717
711
SGFContext (), IsNotTake);
718
712
719
- assert (refType.isExistentialType () &&
713
+ assert (refType.isAnyExistentialType () &&
720
714
" base for open existential component must be an existential" );
721
- assert (refType.getPreferredExistentialRepresentation (SGF.SGM .M )
722
- == ExistentialRepresentation::Class);
723
- auto ref = SGF.B .createOpenExistentialRef (
724
- loc, result, getTypeOfRValue ());
715
+ ManagedValue ref;
716
+ if (refType.is <ExistentialMetatypeType>()) {
717
+ assert (refType.getPreferredExistentialRepresentation (SGF.SGM .M )
718
+ == ExistentialRepresentation::Metatype);
719
+ ref = ManagedValue::forUnmanaged (
720
+ SGF.B .createOpenExistentialMetatype (loc,
721
+ result.getUnmanagedValue (),
722
+ getTypeOfRValue ()));
723
+ } else {
724
+ assert (refType.getPreferredExistentialRepresentation (SGF.SGM .M )
725
+ == ExistentialRepresentation::Class);
726
+ ref = SGF.B .createOpenExistentialRef (loc, result, getTypeOfRValue ());
727
+ }
725
728
726
- SGF.setArchetypeOpeningSite (cast<ArchetypeType>(getSubstFormalType ()),
727
- ref.getValue ());
729
+ SGF.setArchetypeOpeningSite (OpenedArchetype, ref.getValue ());
728
730
729
731
return RValue (SGF, loc, getSubstFormalType (), ref);
730
732
}
@@ -734,15 +736,24 @@ namespace {
734
736
auto payload = std::move (value).forwardAsSingleValue (SGF, loc);
735
737
736
738
SmallVector<ProtocolConformanceRef, 2 > conformances;
737
- for (auto proto : cast<ArchetypeType>( getSubstFormalType ()) ->getConformsTo ())
739
+ for (auto proto : OpenedArchetype ->getConformsTo ())
738
740
conformances.push_back (ProtocolConformanceRef (proto));
739
741
740
- auto ref = SGF.B .createInitExistentialRef (
741
- loc,
742
- base.getType ().getObjectType (),
743
- getSubstFormalType (),
744
- payload,
745
- SGF.getASTContext ().AllocateCopy (conformances));
742
+ SILValue ref;
743
+ if (base.getType ().is <ExistentialMetatypeType>()) {
744
+ ref = SGF.B .createInitExistentialMetatype (
745
+ loc,
746
+ payload,
747
+ base.getType ().getObjectType (),
748
+ SGF.getASTContext ().AllocateCopy (conformances));
749
+ } else {
750
+ ref = SGF.B .createInitExistentialRef (
751
+ loc,
752
+ base.getType ().getObjectType (),
753
+ getSubstFormalType (),
754
+ payload,
755
+ SGF.getASTContext ().AllocateCopy (conformances));
756
+ }
746
757
747
758
auto &TL = SGF.getTypeLowering (base.getType ());
748
759
SGF.emitSemanticStore (loc, ref,
@@ -752,13 +763,13 @@ namespace {
752
763
std::unique_ptr<LogicalPathComponent>
753
764
clone (SILGenFunction &SGF, SILLocation loc) const override {
754
765
LogicalPathComponent *clone =
755
- new OpenClassExistentialComponent (
756
- cast<ArchetypeType>(getSubstFormalType ()));
766
+ new OpenNonOpaqueExistentialComponent (OpenedArchetype, getTypeData ());
757
767
return std::unique_ptr<LogicalPathComponent>(clone);
758
768
}
759
769
760
770
void print (raw_ostream &OS) const override {
761
- OS << " OpenClassExistentialComponent(...)\n " ;
771
+ OS << " OpenNonOpaqueExistentialComponent(" << OpenedArchetype
772
+ << " , ...)\n " ;
762
773
}
763
774
};
764
775
@@ -2076,6 +2087,7 @@ LValue SILGenLValue::visitOpaqueValueExpr(OpaqueValueExpr *e,
2076
2087
lv = SGF.emitOpenExistentialLValue (
2077
2088
opened, std::move (lv),
2078
2089
CanArchetypeType (opened->getOpenedArchetype ()),
2090
+ e->getType ()->getLValueOrInOutObjectType ()->getCanonicalType (),
2079
2091
accessKind);
2080
2092
return lv;
2081
2093
}
@@ -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