Skip to content

Commit 161dd6a

Browse files
authored
Merge pull request #12430 from huonw/silfunctiontype-conformance
[SIL] Witness methods store the conformance from which they come.
2 parents 2b1921b + b5eb418 commit 161dd6a

File tree

131 files changed

+1030
-867
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

131 files changed

+1030
-867
lines changed

include/swift/AST/Attr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class TypeAttributes {
5757
/// If this is an empty attribute specifier, then this will be an invalid loc.
5858
SourceLoc AtLoc;
5959
Optional<StringRef> convention = None;
60+
Optional<StringRef> conventionWitnessMethodProtocol = None;
6061

6162
// For an opened existential type, the known ID.
6263
Optional<UUID> OpenedID;

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,10 @@ ERROR(convention_attribute_expected_name,none,
13391339
"expected convention name identifier in 'convention' attribute", ())
13401340
ERROR(convention_attribute_expected_rparen,none,
13411341
"expected ')' after convention name for 'convention' attribute", ())
1342+
ERROR(convention_attribute_witness_method_expected_colon,none,
1343+
"expected ':' after 'witness_method' for 'convention' attribute", ())
1344+
ERROR(convention_attribute_witness_method_expected_protocol,none,
1345+
"expected protocol name in 'witness_method' 'convention' attribute", ())
13421346

13431347
// objc
13441348
ERROR(attr_objc_missing_colon,none,

include/swift/AST/Types.h

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@
1919

2020
#include "swift/AST/DeclContext.h"
2121
#include "swift/AST/GenericParamKey.h"
22+
#include "swift/AST/Identifier.h"
2223
#include "swift/AST/Ownership.h"
24+
#include "swift/AST/ProtocolConformanceRef.h"
2325
#include "swift/AST/Requirement.h"
2426
#include "swift/AST/SILLayout.h"
2527
#include "swift/AST/SubstitutionList.h"
2628
#include "swift/AST/Type.h"
2729
#include "swift/AST/TypeAlignments.h"
28-
#include "swift/AST/Identifier.h"
2930
#include "swift/Basic/ArrayRefView.h"
3031
#include "swift/Basic/UUID.h"
3132
#include "llvm/ADT/ArrayRef.h"
@@ -3347,6 +3348,7 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
33473348
// CanType? // if NumResults > 1, all result cache
33483349

33493350
CanGenericSignature GenericSig;
3351+
Optional<ProtocolConformanceRef> WitnessMethodConformance;
33503352

33513353
MutableArrayRef<SILParameterInfo> getMutableParameters() {
33523354
return {getTrailingObjects<SILParameterInfo>(), NumParameters};
@@ -3380,21 +3382,22 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
33803382
return *(reinterpret_cast<CanType *>(ptr) + 1);
33813383
}
33823384

3383-
SILFunctionType(GenericSignature *genericSig, ExtInfo ext,
3384-
ParameterConvention calleeConvention,
3385-
ArrayRef<SILParameterInfo> params,
3386-
ArrayRef<SILResultInfo> normalResults,
3387-
Optional<SILResultInfo> errorResult, const ASTContext &ctx,
3388-
RecursiveTypeProperties properties);
3385+
SILFunctionType(
3386+
GenericSignature *genericSig, ExtInfo ext,
3387+
ParameterConvention calleeConvention, ArrayRef<SILParameterInfo> params,
3388+
ArrayRef<SILResultInfo> normalResults,
3389+
Optional<SILResultInfo> errorResult, const ASTContext &ctx,
3390+
RecursiveTypeProperties properties,
3391+
Optional<ProtocolConformanceRef> witnessMethodConformance = None);
33893392

33903393
public:
3391-
static CanSILFunctionType get(GenericSignature *genericSig,
3392-
ExtInfo ext,
3393-
ParameterConvention calleeConvention,
3394-
ArrayRef<SILParameterInfo> interfaceParams,
3395-
ArrayRef<SILResultInfo> interfaceResults,
3396-
Optional<SILResultInfo> interfaceErrorResult,
3397-
const ASTContext &ctx);
3394+
static CanSILFunctionType
3395+
get(GenericSignature *genericSig, ExtInfo ext,
3396+
ParameterConvention calleeConvention,
3397+
ArrayRef<SILParameterInfo> interfaceParams,
3398+
ArrayRef<SILResultInfo> interfaceResults,
3399+
Optional<SILResultInfo> interfaceErrorResult, const ASTContext &ctx,
3400+
Optional<ProtocolConformanceRef> witnessMethodConformance = None);
33983401

33993402
/// Given that this function type uses a C-language convention, return its
34003403
/// formal semantic result type.
@@ -3551,6 +3554,20 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
35513554
/// Self type.
35523555
ClassDecl *getWitnessMethodClass(ModuleDecl &M) const;
35533556

3557+
/// If this is a @convention(witness_method) function, return the conformance
3558+
/// for which the method is a witness.
3559+
ProtocolConformanceRef getWitnessMethodConformance() const {
3560+
assert(getRepresentation() == Representation::WitnessMethod);
3561+
return *WitnessMethodConformance;
3562+
}
3563+
3564+
/// If this is a @convention(witness_method) function, return the conformance
3565+
/// for which the method is a witness, if it isn't that convention, return
3566+
/// None.
3567+
Optional<ProtocolConformanceRef> getWitnessMethodConformanceOrNone() const {
3568+
return WitnessMethodConformance;
3569+
}
3570+
35543571
ExtInfo getExtInfo() const { return ExtInfo(SILFunctionTypeBits.ExtInfo); }
35553572

35563573
/// \brief Returns the language-level calling convention of the function.

include/swift/SIL/SILType.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -572,10 +572,10 @@ NON_SIL_TYPE(AnyFunction)
572572
NON_SIL_TYPE(LValue)
573573
#undef NON_SIL_TYPE
574574

575-
CanSILFunctionType getNativeSILFunctionType(SILModule &M,
576-
Lowering::AbstractionPattern origType,
577-
CanAnyFunctionType substType,
578-
Optional<SILDeclRef> constant = None);
575+
CanSILFunctionType getNativeSILFunctionType(
576+
SILModule &M, Lowering::AbstractionPattern origType,
577+
CanAnyFunctionType substType, Optional<SILDeclRef> constant = None,
578+
Optional<ProtocolConformanceRef> witnessMethodConformance = None);
579579

580580
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SILType T) {
581581
T.print(OS);

include/swift/SIL/TypeLowering.h

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -67,21 +67,30 @@ inline CanAnyFunctionType adjustFunctionType(CanAnyFunctionType t,
6767

6868
/// Given a SIL function type, return a type that is identical except
6969
/// for using the given ExtInfo.
70-
CanSILFunctionType adjustFunctionType(CanSILFunctionType type,
71-
SILFunctionType::ExtInfo extInfo,
72-
ParameterConvention calleeConv);
73-
inline CanSILFunctionType adjustFunctionType(CanSILFunctionType type,
74-
SILFunctionType::ExtInfo extInfo) {
75-
return adjustFunctionType(type, extInfo, type->getCalleeConvention());
70+
CanSILFunctionType
71+
adjustFunctionType(CanSILFunctionType type, SILFunctionType::ExtInfo extInfo,
72+
ParameterConvention calleeConv,
73+
Optional<ProtocolConformanceRef> witnessMethodConformance);
74+
inline CanSILFunctionType
75+
adjustFunctionType(CanSILFunctionType type, SILFunctionType::ExtInfo extInfo,
76+
Optional<ProtocolConformanceRef> witnessMethodConformance) {
77+
return adjustFunctionType(type, extInfo, type->getCalleeConvention(),
78+
witnessMethodConformance);
7679
}
77-
inline CanSILFunctionType adjustFunctionType(CanSILFunctionType t,
78-
SILFunctionType::Representation rep) {
80+
inline CanSILFunctionType
81+
adjustFunctionType(CanSILFunctionType t, SILFunctionType::Representation rep,
82+
Optional<ProtocolConformanceRef> witnessMethodConformance) {
7983
if (t->getRepresentation() == rep) return t;
8084
auto extInfo = t->getExtInfo().withRepresentation(rep);
81-
82-
return adjustFunctionType(t, extInfo,
83-
extInfo.hasContext() ? DefaultThickCalleeConvention
84-
: ParameterConvention::Direct_Unowned);
85+
86+
return adjustFunctionType(
87+
t, extInfo, extInfo.hasContext() ? DefaultThickCalleeConvention
88+
: ParameterConvention::Direct_Unowned,
89+
witnessMethodConformance);
90+
}
91+
inline CanSILFunctionType
92+
adjustFunctionType(CanSILFunctionType t, SILFunctionType::Representation rep) {
93+
return adjustFunctionType(t, rep, t->getWitnessMethodConformanceOrNone());
8594
}
8695

8796

@@ -658,11 +667,10 @@ class TypeConverter {
658667
/// whose type cannot be represented in the AST because it is
659668
/// a polymorphic function value. This function returns the
660669
/// unsubstituted lowered type of this callback.
661-
CanSILFunctionType
662-
getMaterializeForSetCallbackType(AbstractStorageDecl *storage,
663-
CanGenericSignature genericSig,
664-
Type selfType,
665-
SILFunctionTypeRepresentation rep);
670+
CanSILFunctionType getMaterializeForSetCallbackType(
671+
AbstractStorageDecl *storage, CanGenericSignature genericSig,
672+
Type selfType, SILFunctionTypeRepresentation rep,
673+
Optional<ProtocolConformanceRef> witnessMethodConformance);
666674

667675
/// Return the SILFunctionType for a native function value of the
668676
/// given type.

include/swift/Serialization/ModuleFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 376; // Last change: Outlined CopyAddr
57+
const uint16_t VERSION_MINOR = 377; // Last change: SILFunctionType witness_method conformances
5858

5959
using DeclID = PointerEmbeddedInt<unsigned, 31>;
6060
using DeclIDField = BCFixed<31>;
@@ -742,6 +742,7 @@ namespace decls_block {
742742
// followed by result types/conventions, alternating
743743
// followed by error result type/convention
744744
// followed by generic parameter types
745+
// Optionally a protocol conformance (for witness_methods)
745746
// Trailed by its generic requirements, if any.
746747
>;
747748

lib/AST/ASTContext.cpp

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3805,15 +3805,14 @@ void SILFunctionType::Profile(llvm::FoldingSetNodeID &id,
38053805
if (errorResult) errorResult->profile(id);
38063806
}
38073807

3808-
SILFunctionType::SILFunctionType(GenericSignature *genericSig, ExtInfo ext,
3809-
ParameterConvention calleeConvention,
3810-
ArrayRef<SILParameterInfo> params,
3811-
ArrayRef<SILResultInfo> normalResults,
3812-
Optional<SILResultInfo> errorResult,
3813-
const ASTContext &ctx,
3814-
RecursiveTypeProperties properties)
3815-
: TypeBase(TypeKind::SILFunction, &ctx, properties),
3816-
GenericSig(genericSig) {
3808+
SILFunctionType::SILFunctionType(
3809+
GenericSignature *genericSig, ExtInfo ext,
3810+
ParameterConvention calleeConvention, ArrayRef<SILParameterInfo> params,
3811+
ArrayRef<SILResultInfo> normalResults, Optional<SILResultInfo> errorResult,
3812+
const ASTContext &ctx, RecursiveTypeProperties properties,
3813+
Optional<ProtocolConformanceRef> witnessMethodConformance)
3814+
: TypeBase(TypeKind::SILFunction, &ctx, properties), GenericSig(genericSig),
3815+
WitnessMethodConformance(witnessMethodConformance) {
38173816

38183817
SILFunctionTypeBits.HasErrorResult = errorResult.hasValue();
38193818
SILFunctionTypeBits.ExtInfo = ext.Bits;
@@ -3840,6 +3839,13 @@ SILFunctionType::SILFunctionType(GenericSignature *genericSig, ExtInfo ext,
38403839
getMutableAllResultsCache() = CanType();
38413840
}
38423841
#ifndef NDEBUG
3842+
if (ext.getRepresentation() == Representation::WitnessMethod)
3843+
assert(WitnessMethodConformance &&
3844+
"witness_method SIL function without a conformance");
3845+
else
3846+
assert(!WitnessMethodConformance &&
3847+
"non-witness_method SIL function with a conformance");
3848+
38433849
// Make sure the interface types are sane.
38443850
if (genericSig) {
38453851
for (auto gparam : genericSig->getGenericParams()) {
@@ -3885,12 +3891,11 @@ CanSILBlockStorageType SILBlockStorageType::get(CanType captureType) {
38853891
return CanSILBlockStorageType(storageTy);
38863892
}
38873893

3888-
CanSILFunctionType SILFunctionType::get(GenericSignature *genericSig,
3889-
ExtInfo ext, ParameterConvention callee,
3890-
ArrayRef<SILParameterInfo> params,
3891-
ArrayRef<SILResultInfo> normalResults,
3892-
Optional<SILResultInfo> errorResult,
3893-
const ASTContext &ctx) {
3894+
CanSILFunctionType SILFunctionType::get(
3895+
GenericSignature *genericSig, ExtInfo ext, ParameterConvention callee,
3896+
ArrayRef<SILParameterInfo> params, ArrayRef<SILResultInfo> normalResults,
3897+
Optional<SILResultInfo> errorResult, const ASTContext &ctx,
3898+
Optional<ProtocolConformanceRef> witnessMethodConformance) {
38943899
llvm::FoldingSetNodeID id;
38953900
SILFunctionType::Profile(id, genericSig, ext, callee, params, normalResults,
38963901
errorResult);
@@ -3928,9 +3933,9 @@ CanSILFunctionType SILFunctionType::get(GenericSignature *genericSig,
39283933
properties.removeHasDependentMember();
39293934
}
39303935

3931-
auto fnType =
3932-
new (mem) SILFunctionType(genericSig, ext, callee, params, normalResults,
3933-
errorResult, ctx, properties);
3936+
auto fnType = new (mem)
3937+
SILFunctionType(genericSig, ext, callee, params, normalResults,
3938+
errorResult, ctx, properties, witnessMethodConformance);
39343939
ctx.Impl.SILFunctionTypes.InsertNode(fnType, insertPos);
39353940
return CanSILFunctionType(fnType);
39363941
}

lib/AST/ASTPrinter.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3500,7 +3500,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
35003500
}
35013501
}
35023502

3503-
void printFunctionExtInfo(SILFunctionType::ExtInfo info) {
3503+
void printFunctionExtInfo(
3504+
SILFunctionType::ExtInfo info,
3505+
Optional<ProtocolConformanceRef> witnessMethodConformance) {
35043506
if (Options.SkipAttributes)
35053507
return;
35063508

@@ -3529,7 +3531,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
35293531
Printer << "objc_method";
35303532
break;
35313533
case SILFunctionType::Representation::WitnessMethod:
3532-
Printer << "witness_method";
3534+
Printer << "witness_method: ";
3535+
printTypeDeclName(
3536+
witnessMethodConformance->getRequirement()->getDeclaredType());
35333537
break;
35343538
case SILFunctionType::Representation::Closure:
35353539
Printer << "closure";
@@ -3647,7 +3651,8 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
36473651
}
36483652

36493653
void visitSILFunctionType(SILFunctionType *T) {
3650-
printFunctionExtInfo(T->getExtInfo());
3654+
printFunctionExtInfo(T->getExtInfo(),
3655+
T->getWitnessMethodConformanceOrNone());
36513656
printCalleeConvention(T->getCalleeConvention());
36523657
if (auto sig = T->getGenericSignature()) {
36533658
printGenericSignature(sig,

lib/AST/ProtocolConformance.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,18 @@ ProtocolConformanceRef::subst(Type origType,
8686

8787
// If we have a concrete conformance, we need to substitute the
8888
// conformance to apply to the new type.
89-
if (isConcrete())
89+
if (isConcrete()) {
90+
auto concrete = getConcrete();
91+
if (auto classDecl = concrete->getType()->getClassOrBoundGenericClass()) {
92+
// If this is a class, we need to traffic in the actual type that
93+
// implements the protocol, not 'Self' and not any subclasses (with their
94+
// inherited conformances).
95+
substType =
96+
substType->eraseDynamicSelfType()->getSuperclassForDecl(classDecl);
97+
}
9098
return ProtocolConformanceRef(
9199
getConcrete()->subst(substType, subs, conformances));
100+
}
92101

93102
// Opened existentials trivially conform and do not need to go through
94103
// substitution map lookup.

lib/AST/Type.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3583,13 +3583,11 @@ case TypeKind::Id:
35833583

35843584
if (!changed) return *this;
35853585

3586-
return SILFunctionType::get(fnTy->getGenericSignature(),
3587-
fnTy->getExtInfo(),
3586+
return SILFunctionType::get(fnTy->getGenericSignature(), fnTy->getExtInfo(),
35883587
fnTy->getCalleeConvention(),
3589-
transInterfaceParams,
3590-
transInterfaceResults,
3591-
transErrorResult,
3592-
Ptr->getASTContext());
3588+
transInterfaceParams, transInterfaceResults,
3589+
transErrorResult, Ptr->getASTContext(),
3590+
fnTy->getWitnessMethodConformanceOrNone());
35933591
}
35943592

35953593
case TypeKind::UnownedStorage:

lib/IRGen/GenProto.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,8 @@ bool PolymorphicConvention::considerType(CanType type, IsExact_t isExact,
307307

308308
void PolymorphicConvention::considerWitnessSelf(CanSILFunctionType fnType) {
309309
CanType selfTy = fnType->getSelfInstanceType();
310+
auto conformance = fnType->getWitnessMethodConformance();
311+
auto protocol = conformance.getRequirement();
310312

311313
// First, bind type metadata for Self.
312314
Sources.emplace_back(MetadataSource::Kind::SelfMetadata,
@@ -328,11 +330,7 @@ void PolymorphicConvention::considerWitnessSelf(CanSILFunctionType fnType) {
328330
// The Self type is abstract, so we can fulfill its metadata from
329331
// the Self metadata parameter.
330332
addSelfMetadataFulfillment(selfTy);
331-
332-
// FIXME: We should fulfill the witness table too, but we don't
333-
// have the original protocol anymore -- we should store it as part
334-
// of the @convention(witness_method) bit in the SILFunctionType's
335-
// ExtInfo
333+
addSelfWitnessTableFulfillment(selfTy, protocol);
336334
} else {
337335
// If the Self type is concrete, we have a witness thunk with a
338336
// fully substituted Self type. The witness table parameter is not
@@ -344,6 +342,8 @@ void PolymorphicConvention::considerWitnessSelf(CanSILFunctionType fnType) {
344342
//
345343
// For now, just fulfill the generic arguments of 'Self'.
346344
considerType(selfTy, IsInexact, Sources.size() - 1, MetadataPath());
345+
346+
addSelfWitnessTableFulfillment(selfTy, protocol);
347347
}
348348
}
349349

lib/IRGen/LoadableByAddress.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ getNewSILFunctionTypePtr(GenericEnvironment *GenericEnv,
180180
currSILFunctionType->getCalleeConvention(), newArgTys,
181181
getNewResults(GenericEnv, currSILFunctionType, Mod),
182182
currSILFunctionType->getOptionalErrorResult(),
183-
currSILFunctionType->getASTContext());
183+
currSILFunctionType->getASTContext(),
184+
currSILFunctionType->getWitnessMethodConformanceOrNone());
184185
return newSILFunctionType;
185186
}
186187

@@ -2105,7 +2106,8 @@ static bool rewriteFunctionReturn(StructLoweringState &pass) {
21052106
loweredTy->getGenericSignature(), loweredTy->getExtInfo(),
21062107
loweredTy->getCalleeConvention(), loweredTy->getParameters(),
21072108
newSILResultInfo, loweredTy->getOptionalErrorResult(),
2108-
F->getModule().getASTContext());
2109+
F->getModule().getASTContext(),
2110+
loweredTy->getWitnessMethodConformanceOrNone());
21092111
F->rewriteLoweredTypeUnsafe(NewTy);
21102112
return true;
21112113
} else if (isLargeLoadableType(genEnv, resultTy, pass.Mod)) {

0 commit comments

Comments
 (0)