Skip to content

Commit f7d81f7

Browse files
committed
Swift SIL: deal with a generic self type in SubstitutionMap.getMethodSubstitutions
If the method is a default witness methods (`selfType` != nil) it has generic self type. In this case the generic self parameter is at depth 0 and the actual generic parameters of the substitution map are at depth + 1, e.g: ``` @convention(witness_method: P) <τ_0_0><τ_1_0 where τ_0_0 : GenClass<τ_1_0>.T> ^ ^ self params of substitution map at depth + 1 ```
1 parent 655dae8 commit f7d81f7

File tree

5 files changed

+50
-5
lines changed

5 files changed

+50
-5
lines changed

SwiftCompilerSources/Sources/SIL/ASTExtensions.swift

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,19 @@ extension ClassDecl {
5050
}
5151

5252
extension SubstitutionMap {
53-
public func getMethodSubstitutions(for method: Function) -> SubstitutionMap {
54-
return SubstitutionMap(bridged: method.bridged.getMethodSubstitutions(bridged))
53+
/// Returns the substitutions to specialize a method.
54+
///
55+
/// If this is a default witness methods (`selfType` != nil) it has generic self type. In this case
56+
/// the generic self parameter is at depth 0 and the actual generic parameters of the substitution map
57+
/// are at depth + 1, e.g:
58+
/// ```
59+
/// @convention(witness_method: P) <τ_0_0><τ_1_0 where τ_0_0 : GenClass<τ_1_0>.T>
60+
/// ^ ^
61+
/// self params of substitution map at depth + 1
62+
/// ```
63+
public func getMethodSubstitutions(for method: Function, selfType: CanonicalType? = nil) -> SubstitutionMap {
64+
return SubstitutionMap(bridged: method.bridged.getMethodSubstitutions(bridged,
65+
selfType?.bridged ?? BridgedCanType()))
5566
}
5667
}
5768

include/swift/AST/ASTBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3123,6 +3123,7 @@ class BridgedCanType {
31233123
swift::TypeBase * _Nullable type;
31243124

31253125
public:
3126+
BRIDGED_INLINE BridgedCanType();
31263127
BRIDGED_INLINE BridgedCanType(swift::CanType ty);
31273128
BRIDGED_INLINE swift::CanType unbridged() const;
31283129
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getRawType() const;

include/swift/AST/ASTBridgingImpl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,9 @@ static_assert((int)BridgedASTType::MetatypeRepresentation::ObjC == (int)swift::M
623623
// MARK: BridgedCanType
624624
//===----------------------------------------------------------------------===//
625625

626+
BridgedCanType::BridgedCanType() : type(nullptr) {
627+
}
628+
626629
BridgedCanType::BridgedCanType(swift::CanType ty) : type(ty.getPointer()) {
627630
}
628631

include/swift/SIL/SILBridging.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,8 @@ struct BridgedFunction {
516516
bool isConvertPointerToPointerArgument() const;
517517
bool isAutodiffVJP() const;
518518
SwiftInt specializationLevel() const;
519-
SWIFT_IMPORT_UNSAFE BridgedSubstitutionMap getMethodSubstitutions(BridgedSubstitutionMap contextSubs) const;
519+
SWIFT_IMPORT_UNSAFE BridgedSubstitutionMap getMethodSubstitutions(BridgedSubstitutionMap contextSubs,
520+
BridgedCanType selfType) const;
520521
BRIDGED_INLINE OptionalSourceFileKind getSourceFileKind() const;
521522

522523
enum class ParseEffectsMode {

lib/SIL/Utils/SILBridging.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,15 +197,44 @@ BridgedOwnedString BridgedFunction::getDebugDescription() const {
197197
return BridgedOwnedString(str);
198198
}
199199

200-
BridgedSubstitutionMap BridgedFunction::getMethodSubstitutions(BridgedSubstitutionMap contextSubs) const {
200+
BridgedSubstitutionMap BridgedFunction::getMethodSubstitutions(BridgedSubstitutionMap contextSubstitutions,
201+
BridgedCanType selfType) const {
201202
swift::SILFunction *f = getFunction();
202203
swift::GenericSignature genericSig = f->getLoweredFunctionType()->getInvocationGenericSignature();
203204

204205
if (!genericSig || genericSig->areAllParamsConcrete())
205206
return swift::SubstitutionMap();
206207

208+
SubstitutionMap contextSubs = contextSubstitutions.unbridged();
209+
if (selfType.unbridged() &&
210+
contextSubs.getGenericSignature().getGenericParams().size() + 1 == genericSig.getGenericParams().size()) {
211+
212+
// If this is a default witness methods (`selfType` != nil) it has generic self type. In this case
213+
// the generic self parameter is at depth 0 and the actual generic parameters of the substitution map
214+
// are at depth + 1, e.g:
215+
// ```
216+
// @convention(witness_method: P) <τ_0_0><τ_1_0 where τ_0_0 : GenClass<τ_1_0>.T>
217+
// ^ ^
218+
// self params of substitution map at depth + 1
219+
// ```
220+
return swift::SubstitutionMap::get(genericSig,
221+
[&](SubstitutableType *type) -> Type {
222+
GenericTypeParamType *genericParam = cast<GenericTypeParamType>(type);
223+
// The self type is τ_0_0
224+
if (genericParam->getDepth() == 0 && genericParam->getIndex() == 0)
225+
return selfType.unbridged();
226+
227+
// Lookup the substitution map types at depth - 1.
228+
auto *depthMinus1Param = GenericTypeParamType::getType(genericParam->getDepth() - 1,
229+
genericParam->getIndex(),
230+
genericParam->getASTContext());
231+
return swift::QuerySubstitutionMap{contextSubs}(depthMinus1Param);
232+
},
233+
swift::LookUpConformanceInModule());
234+
235+
}
207236
return swift::SubstitutionMap::get(genericSig,
208-
swift::QuerySubstitutionMap{contextSubs.unbridged()},
237+
swift::QuerySubstitutionMap{contextSubs},
209238
swift::LookUpConformanceInModule());
210239
}
211240

0 commit comments

Comments
 (0)