Skip to content

Commit f5e75bb

Browse files
authored
Merge pull request #59546 from CodaFi/rebastract-art
2 parents c5fe743 + 33f9436 commit f5e75bb

File tree

7 files changed

+168
-6
lines changed

7 files changed

+168
-6
lines changed

include/swift/AST/Types.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5313,8 +5313,8 @@ class ParameterizedProtocolType final : public TypeBase,
53135313
public:
53145314
/// Retrieve an instance of a protocol composition type with the
53155315
/// given set of members.
5316-
static Type get(const ASTContext &C, ProtocolType *base,
5317-
ArrayRef<Type> args);
5316+
static ParameterizedProtocolType *get(const ASTContext &C, ProtocolType *base,
5317+
ArrayRef<Type> args);
53185318

53195319
ProtocolType *getBaseType() const {
53205320
return Base;
@@ -5354,6 +5354,13 @@ class ParameterizedProtocolType final : public TypeBase,
53545354
RecursiveTypeProperties properties);
53555355
};
53565356
BEGIN_CAN_TYPE_WRAPPER(ParameterizedProtocolType, Type)
5357+
static CanParameterizedProtocolType get(const ASTContext &C,
5358+
ProtocolType *base,
5359+
ArrayRef<Type> args) {
5360+
return CanParameterizedProtocolType(
5361+
ParameterizedProtocolType::get(C, base, args));
5362+
}
5363+
53575364
CanProtocolType getBaseType() const {
53585365
return CanProtocolType(getPointer()->getBaseType());
53595366
}
@@ -5420,6 +5427,7 @@ class ExistentialType final : public TypeBase {
54205427
}
54215428
};
54225429
BEGIN_CAN_TYPE_WRAPPER(ExistentialType, Type)
5430+
static CanExistentialType get(CanType constraint);
54235431
PROXY_CAN_TYPE_SIMPLE_GETTER(getConstraintType)
54245432
END_CAN_TYPE_WRAPPER(ExistentialType, Type)
54255433

include/swift/SIL/AbstractionPattern.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,6 +1361,10 @@ class AbstractionPattern {
13611361
/// it.
13621362
AbstractionPattern getReferenceStorageReferentType() const;
13631363

1364+
/// Give that the value being abstracted is an existential, return the
1365+
/// underlying constraint type.
1366+
AbstractionPattern getExistentialConstraintType() const;
1367+
13641368
/// Given that the value being abstracted is a function type, return the
13651369
/// abstraction pattern for the derivative function.
13661370
///

lib/AST/ASTContext.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3324,9 +3324,9 @@ ProtocolCompositionType::build(const ASTContext &C, ArrayRef<Type> Members,
33243324
return compTy;
33253325
}
33263326

3327-
Type ParameterizedProtocolType::get(const ASTContext &C,
3328-
ProtocolType *baseTy,
3329-
ArrayRef<Type> args) {
3327+
ParameterizedProtocolType *ParameterizedProtocolType::get(const ASTContext &C,
3328+
ProtocolType *baseTy,
3329+
ArrayRef<Type> args) {
33303330
assert(args.size() > 0);
33313331

33323332
bool isCanonical = baseTy->isCanonical();

lib/AST/Type.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1631,7 +1631,7 @@ CanType TypeBase::computeCanonicalType() {
16311631
for (Type t : PPT->getArgs())
16321632
CanArgs.push_back(t->getCanonicalType());
16331633
auto &C = Base->getASTContext();
1634-
Result = ParameterizedProtocolType::get(C, Base, CanArgs).getPointer();
1634+
Result = ParameterizedProtocolType::get(C, Base, CanArgs);
16351635
break;
16361636
}
16371637
case TypeKind::Existential: {
@@ -3844,6 +3844,15 @@ operator()(CanType maybeOpaqueType, Type replacementType,
38443844
return substRef;
38453845
}
38463846

3847+
CanExistentialType CanExistentialType::get(CanType constraint) {
3848+
assert(!(constraint->isAny() || constraint->isAnyObject()) &&
3849+
"Any(Object) may not apppear as canonical constraint type");
3850+
assert(!constraint->is<ExistentialMetatypeType>() &&
3851+
"Existential metatype may not apppear as canonical constraint type");
3852+
return CanExistentialType(
3853+
ExistentialType::get(constraint)->castTo<ExistentialType>());
3854+
}
3855+
38473856
CanPrimaryArchetypeType
38483857
PrimaryArchetypeType::getNew(const ASTContext &Ctx,
38493858
GenericEnvironment *GenericEnv,

lib/SIL/IR/AbstractionPattern.cpp

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,58 @@ AbstractionPattern AbstractionPattern::getReferenceStorageReferentType() const {
944944
llvm_unreachable("bad kind");
945945
}
946946

947+
static CanType getExistentialConstraintType(CanType type) {
948+
assert(type.isExistentialType());
949+
if (auto *ET = type->getAs<ExistentialType>()) {
950+
return CanType(ET->getConstraintType());
951+
}
952+
return type;
953+
}
954+
955+
AbstractionPattern AbstractionPattern::getExistentialConstraintType() const {
956+
switch (getKind()) {
957+
case Kind::Invalid:
958+
llvm_unreachable("querying invalid abstraction pattern!");
959+
case Kind::ObjCMethodType:
960+
case Kind::CurriedObjCMethodType:
961+
case Kind::PartialCurriedObjCMethodType:
962+
case Kind::CFunctionAsMethodType:
963+
case Kind::CurriedCFunctionAsMethodType:
964+
case Kind::PartialCurriedCFunctionAsMethodType:
965+
case Kind::CXXMethodType:
966+
case Kind::CurriedCXXMethodType:
967+
case Kind::PartialCurriedCXXMethodType:
968+
case Kind::Tuple:
969+
case Kind::OpaqueFunction:
970+
case Kind::OpaqueDerivativeFunction:
971+
case Kind::ObjCCompletionHandlerArgumentsType:
972+
case Kind::CXXOperatorMethodType:
973+
case Kind::CurriedCXXOperatorMethodType:
974+
case Kind::PartialCurriedCXXOperatorMethodType:
975+
llvm_unreachable("pattern for function or tuple cannot be for existential");
976+
977+
case Kind::Opaque:
978+
return *this;
979+
980+
case Kind::Type:
981+
if (isTypeParameterOrOpaqueArchetype())
982+
return AbstractionPattern::getOpaque();
983+
return AbstractionPattern(getGenericSignature(),
984+
::getExistentialConstraintType(getType()));
985+
986+
case Kind::Discard:
987+
return AbstractionPattern::getDiscard(
988+
getGenericSignature(), ::getExistentialConstraintType(getType()));
989+
990+
case Kind::ClangType:
991+
// This is not reflected in clang types.
992+
return AbstractionPattern(getGenericSignature(),
993+
::getExistentialConstraintType(getType()),
994+
getClangType());
995+
}
996+
llvm_unreachable("bad kind");
997+
}
998+
947999
void AbstractionPattern::dump() const {
9481000
print(llvm::errs());
9491001
llvm::errs() << "\n";
@@ -1705,6 +1757,44 @@ class SubstFunctionTypePatternVisitor
17051757
llvm_unreachable("Unimplemented!");
17061758
}
17071759

1760+
CanType visitExistentialType(ExistentialType *exist,
1761+
AbstractionPattern pattern) {
1762+
if (auto gp = handleTypeParameterInAbstractionPattern(pattern, exist))
1763+
return gp;
1764+
1765+
// Avoid walking into the constraint type if we can help it.
1766+
if (!exist->hasTypeParameter() && !exist->hasArchetype() &&
1767+
!exist->hasOpaqueArchetype()) {
1768+
return CanType(exist);
1769+
}
1770+
1771+
return CanExistentialType::get(visit(
1772+
exist->getConstraintType(), pattern.getExistentialConstraintType()));
1773+
}
1774+
1775+
CanType visitParameterizedProtocolType(ParameterizedProtocolType *ppt,
1776+
AbstractionPattern pattern) {
1777+
if (auto gp = handleTypeParameterInAbstractionPattern(pattern, ppt))
1778+
return gp;
1779+
1780+
// Recurse into the arguments of the parameterized protocol.
1781+
SmallVector<Type, 4> substArgs;
1782+
auto origPPT = pattern.getAs<ParameterizedProtocolType>();
1783+
if (!origPPT)
1784+
return CanType(ppt);
1785+
1786+
for (unsigned i = 0; i < ppt->getArgs().size(); ++i) {
1787+
auto argTy = ppt->getArgs()[i];
1788+
auto origArgTy = AbstractionPattern(pattern.getGenericSignatureOrNull(),
1789+
origPPT.getArgs()[i]);
1790+
auto substEltTy = visit(argTy, origArgTy);
1791+
substArgs.push_back(substEltTy);
1792+
}
1793+
1794+
return CanType(ParameterizedProtocolType::get(
1795+
TC.Context, ppt->getBaseType(), substArgs));
1796+
}
1797+
17081798
CanType visitTupleType(TupleType *tuple, AbstractionPattern pattern) {
17091799
if (auto gp = handleTypeParameterInAbstractionPattern(pattern, tuple))
17101800
return gp;

lib/SIL/IR/TypeLowering.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2265,6 +2265,47 @@ TypeConverter::computeLoweredRValueType(TypeExpansionContext forExpansion,
22652265
MetatypeRepresentation::Thick);
22662266
}
22672267

2268+
CanType visitExistentialType(CanExistentialType substExistType) {
2269+
// Try to avoid walking into the constraint type if we can help it
2270+
if (!substExistType->hasTypeParameter() &&
2271+
!substExistType->hasArchetype() &&
2272+
!substExistType->hasOpaqueArchetype()) {
2273+
return substExistType;
2274+
}
2275+
2276+
return CanExistentialType::get(visit(substExistType.getConstraintType()));
2277+
}
2278+
2279+
CanType
2280+
visitParameterizedProtocolType(CanParameterizedProtocolType substPPT) {
2281+
bool changed = false;
2282+
SmallVector<Type, 4> loweredSubstArgs;
2283+
loweredSubstArgs.reserve(substPPT.getArgs().size());
2284+
2285+
auto origConstraint = origType.getExistentialConstraintType();
2286+
auto origPPT = origConstraint.getAs<ParameterizedProtocolType>();
2287+
if (!origPPT)
2288+
return substPPT;
2289+
2290+
for (auto i : indices(substPPT.getArgs())) {
2291+
auto origArgTy = AbstractionPattern(
2292+
origConstraint.getGenericSignatureOrNull(), origPPT.getArgs()[i]);
2293+
auto substArgType = substPPT.getArgs()[i];
2294+
2295+
CanType loweredSubstEltType =
2296+
TC.getLoweredRValueType(forExpansion, origArgTy, substArgType);
2297+
changed = changed || substArgType != loweredSubstEltType;
2298+
2299+
loweredSubstArgs.push_back(loweredSubstEltType);
2300+
}
2301+
2302+
if (!changed)
2303+
return substPPT;
2304+
2305+
return CanParameterizedProtocolType::get(
2306+
TC.Context, substPPT->getBaseType(), loweredSubstArgs);
2307+
}
2308+
22682309
CanType visitPackType(CanPackType substPackType) {
22692310
llvm_unreachable("");
22702311
}

test/SILGen/parameterized_existentials.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ struct S: Q {
2222
typealias Z = Float
2323
}
2424

25+
struct R<T, U, V> {
26+
var force: () -> any P<T, U, V>
27+
// CHECK-LABEL: sil hidden [ossa] @$s13parameterized1RV5forceACyxq_q0_GAA1P_pyxq_q0_XPyc_tcfC : $@convention(method) <T, U, V> (@owned @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> () -> @out P<τ_0_0, τ_0_1, τ_0_2> for <T, U, V>, @thin R<T, U, V>.Type) -> @owned R<T, U, V> {
28+
}
29+
2530
// CHECK-LABEL: sil hidden [ossa] @$s13parameterized6upcastyAA1P_pAA1SVF : $@convention(thin) (S) -> @out P {
2631
func upcast(_ x: S) -> any P {
2732
// CHECK: bb0([[RESULT_PARAM:%.*]] : $*P, [[CONCRETE_VAL:%.*]] : $S):
@@ -88,3 +93,8 @@ func upcastResult() {
8893

8994
reuse({ () -> any Q<Int, String, Float> in S() })
9095
}
96+
97+
// CHECK-LABEL: sil hidden [ossa] @$s13parameterized5forceAA1P_pyxq_q0_XPyr1_lF : $@convention(thin) <T, U, V> () -> @out P<T, U, V> {
98+
func force<T, U, V>() -> any P<T, U, V> {
99+
return R(force: { force() }).force()
100+
}

0 commit comments

Comments
 (0)