Skip to content

Commit 2c2f8a3

Browse files
authored
Merge pull request swiftlang#21786 from slavapestov/dynamic-self-is-so-broken
Some fixes for DynamicSelfType
2 parents e8a6646 + 5ade432 commit 2c2f8a3

File tree

9 files changed

+183
-46
lines changed

9 files changed

+183
-46
lines changed

lib/AST/Type.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4047,9 +4047,15 @@ void SILBoxType::Profile(llvm::FoldingSetNodeID &id, SILLayout *Layout,
40474047
Substitutions.profile(id);
40484048
}
40494049

4050-
static RecursiveTypeProperties getRecursivePropertiesOfMap(
4051-
SubstitutionMap subMap) {
4050+
static RecursiveTypeProperties getBoxRecursiveProperties(
4051+
SILLayout *Layout, SubstitutionMap subMap) {
40524052
RecursiveTypeProperties props;
4053+
for (auto &field : Layout->getFields()) {
4054+
auto fieldProps = field.getLoweredType()->getRecursiveProperties();
4055+
fieldProps.removeHasTypeParameter();
4056+
fieldProps.removeHasDependentMember();
4057+
props |= fieldProps;
4058+
}
40534059
for (auto replacementType : subMap.getReplacementTypes()) {
40544060
if (replacementType) props |= replacementType->getRecursiveProperties();
40554061
}
@@ -4058,7 +4064,8 @@ static RecursiveTypeProperties getRecursivePropertiesOfMap(
40584064

40594065
SILBoxType::SILBoxType(ASTContext &C,
40604066
SILLayout *Layout, SubstitutionMap Substitutions)
4061-
: TypeBase(TypeKind::SILBox, &C, getRecursivePropertiesOfMap(Substitutions)),
4067+
: TypeBase(TypeKind::SILBox, &C,
4068+
getBoxRecursiveProperties(Layout, Substitutions)),
40624069
Layout(Layout), Substitutions(Substitutions) {
40634070
assert(Substitutions.isCanonical());
40644071
}

lib/SIL/TypeLowering.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1819,7 +1819,7 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
18191819

18201820
FuncDecl *func = cast<FuncDecl>(vd);
18211821
auto funcTy = cast<AnyFunctionType>(
1822-
func->getInterfaceType()->eraseDynamicSelfType()->getCanonicalType());
1822+
func->getInterfaceType()->getCanonicalType());
18231823
return getFunctionInterfaceTypeWithCaptures(funcTy, func);
18241824
}
18251825

@@ -2131,7 +2131,11 @@ TypeConverter::getLoweredLocalCaptures(AnyFunctionRef fn) {
21312131

21322132
// We're capturing a 'self' value with dynamic 'Self' type;
21332133
// handle it specially.
2134-
if (captureType->getClassOrBoundGenericClass()) {
2134+
//
2135+
// However, only do this if its a 'let'; if the capture is
2136+
// mutable, we're going to be capturing a box or an address.
2137+
if (captureType->getClassOrBoundGenericClass() &&
2138+
capturedVar->isLet()) {
21352139
if (selfCapture)
21362140
selfCapture = selfCapture->mergeFlags(capture);
21372141
else

lib/SILGen/SILGenBridging.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -934,9 +934,11 @@ SILGenFunction::emitBlockToFunc(SILLocation loc,
934934
loweredFuncTy, loweredFuncTy->getExtInfo().withNoEscape(false),
935935
loweredFuncTy->getWitnessMethodConformanceOrNone());
936936

937+
CanType dynamicSelfType;
937938
auto thunkTy = buildThunkType(loweredBlockTy, loweredFuncTyWithoutNoEscape,
938939
inputSubstType, outputSubstType,
939-
genericEnv, interfaceSubs);
940+
genericEnv, interfaceSubs, dynamicSelfType);
941+
assert(!dynamicSelfType && "Not implemented");
940942

941943
auto thunk = SGM.getOrCreateReabstractionThunk(thunkTy,
942944
loweredBlockTy,

lib/SILGen/SILGenFunction.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1761,6 +1761,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
17611761
CanType &outputSubstType,
17621762
GenericEnvironment *&genericEnv,
17631763
SubstitutionMap &interfaceSubs,
1764+
CanType &dynamicSelfType,
17641765
bool withoutActuallyEscaping=false);
17651766

17661767
//===--------------------------------------------------------------------===//

lib/SILGen/SILGenPoly.cpp

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,15 @@ ManagedValue Transform::transform(ManagedValue v,
466466

467467
// Subtype conversions:
468468

469+
// A base class method returning Self can be used in place of a derived
470+
// class method returning Self.
471+
if (auto outputSelfType = dyn_cast<DynamicSelfType>(outputSubstType)) {
472+
if (auto inputSelfType = dyn_cast<DynamicSelfType>(inputSubstType)) {
473+
inputSubstType = inputSelfType.getSelfType();
474+
outputSubstType = outputSelfType.getSelfType();
475+
}
476+
}
477+
469478
// - upcasts for classes
470479
if (outputSubstType->getClassOrBoundGenericClass() &&
471480
inputSubstType->getClassOrBoundGenericClass()) {
@@ -482,7 +491,9 @@ ManagedValue Transform::transform(ManagedValue v,
482491
// Upcast to a superclass.
483492
return SGF.B.createUpcast(Loc, v, loweredResultTy);
484493
} else {
485-
// Unchecked-downcast to a covariant return type.
494+
// FIXME: Should only happen with the DynamicSelfType case above,
495+
// except that convenience inits return the static self and not
496+
// DynamicSelfType.
486497
assert(inputSubstType->isExactSuperclassOf(outputSubstType)
487498
&& "should be inheritance relationship between input and output");
488499
return SGF.B.createUncheckedRefCast(Loc, v, loweredResultTy);
@@ -2806,11 +2817,14 @@ void ResultPlanner::execute(ArrayRef<SILValue> innerDirectResults,
28062817
/// \param inputSubstType Formal AST type of function value being thunked
28072818
/// \param outputOrigType Abstraction pattern of the thunk
28082819
/// \param outputSubstType Formal AST type of the thunk
2820+
/// \param dynamicSelfType If true, the last parameter is a dummy used to pass
2821+
/// DynamicSelfType metadata
28092822
static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
28102823
AbstractionPattern inputOrigType,
28112824
CanAnyFunctionType inputSubstType,
28122825
AbstractionPattern outputOrigType,
2813-
CanAnyFunctionType outputSubstType) {
2826+
CanAnyFunctionType outputSubstType,
2827+
CanType dynamicSelfType) {
28142828
PrettyStackTraceSILFunction stackTrace("emitting reabstraction thunk in",
28152829
&SGF.F);
28162830
auto thunkType = SGF.F.getLoweredFunctionType();
@@ -2820,6 +2834,11 @@ static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
28202834
SmallVector<ManagedValue, 8> params;
28212835
SGF.collectThunkParams(loc, params);
28222836

2837+
// Ignore the self parameter at the SIL level. IRGen will use it to
2838+
// recover type metadata.
2839+
if (dynamicSelfType)
2840+
params.pop_back();
2841+
28232842
ManagedValue fnValue = params.pop_back_val();
28242843
auto fnType = fnValue.getType().castTo<SILFunctionType>();
28252844
assert(!fnType->isPolymorphic());
@@ -2969,6 +2988,7 @@ CanSILFunctionType SILGenFunction::buildThunkType(
29692988
CanType &outputSubstType,
29702989
GenericEnvironment *&genericEnv,
29712990
SubstitutionMap &interfaceSubs,
2991+
CanType &dynamicSelfType,
29722992
bool withoutActuallyEscaping) {
29732993
assert(!expectedType->isPolymorphic());
29742994
assert(!sourceType->isPolymorphic());
@@ -3069,6 +3089,18 @@ CanSILFunctionType SILGenFunction::buildThunkType(
30693089
? contextConvention
30703090
: ParameterConvention::Direct_Unowned});
30713091

3092+
// If this thunk involves DynamicSelfType in any way, add a capture for it
3093+
// in case we need to recover metadata.
3094+
if (sourceType->hasDynamicSelfType() ||
3095+
expectedType->hasDynamicSelfType()) {
3096+
dynamicSelfType = F.getSelfMetadataArgument()->getType().getASTType();
3097+
if (!isa<MetatypeType>(dynamicSelfType)) {
3098+
dynamicSelfType = CanMetatypeType::get(dynamicSelfType,
3099+
MetatypeRepresentation::Thick);
3100+
}
3101+
params.push_back({dynamicSelfType, ParameterConvention::Direct_Unowned});
3102+
}
3103+
30723104
// Map the parameter and expected types out of context to get the interface
30733105
// type of the thunk.
30743106
SmallVector<SILParameterInfo, 4> interfaceParams;
@@ -3136,11 +3168,13 @@ static ManagedValue createThunk(SILGenFunction &SGF,
31363168
GenericEnvironment *genericEnv = nullptr;
31373169
auto toType = expectedType->getWithExtInfo(
31383170
expectedType->getExtInfo().withNoEscape(false));
3171+
CanType dynamicSelfType;
31393172
auto thunkType = SGF.buildThunkType(sourceType, toType,
31403173
inputSubstType,
31413174
outputSubstType,
31423175
genericEnv,
3143-
interfaceSubs);
3176+
interfaceSubs,
3177+
dynamicSelfType);
31443178
auto thunk = SGF.SGM.getOrCreateReabstractionThunk(
31453179
thunkType,
31463180
sourceType,
@@ -3156,7 +3190,8 @@ static ManagedValue createThunk(SILGenFunction &SGF,
31563190
inputOrigType,
31573191
inputSubstType,
31583192
outputOrigType,
3159-
outputSubstType);
3193+
outputSubstType,
3194+
dynamicSelfType);
31603195
}
31613196

31623197
CanSILFunctionType substFnType = thunkType;
@@ -3168,10 +3203,18 @@ static ManagedValue createThunk(SILGenFunction &SGF,
31683203

31693204
// Create it in our current function.
31703205
auto thunkValue = SGF.B.createFunctionRefFor(loc, thunk);
3206+
SmallVector<ManagedValue, 2> thunkArgs;
3207+
thunkArgs.push_back(fn.ensurePlusOne(SGF, loc));
3208+
if (dynamicSelfType) {
3209+
SILType dynamicSILType = SGF.getLoweredType(dynamicSelfType);
3210+
SILValue value = SGF.B.createMetatype(loc, dynamicSILType);
3211+
thunkArgs.push_back(ManagedValue::forUnmanaged(value));
3212+
}
3213+
31713214
ManagedValue thunkedFn =
31723215
SGF.B.createPartialApply(loc, thunkValue,
31733216
SILType::getPrimitiveObjectType(substFnType),
3174-
interfaceSubs, fn.ensurePlusOne(SGF, loc),
3217+
interfaceSubs, thunkArgs,
31753218
SILType::getPrimitiveObjectType(toType));
31763219

31773220
if (!expectedType->isNoEscape()) {
@@ -3193,10 +3236,14 @@ static CanSILFunctionType buildWithoutActuallyEscapingThunkType(
31933236
noEscapingType->getExtInfo().withNoEscape(false));
31943237

31953238
CanType inputSubstType, outputSubstType;
3196-
return SGF.buildThunkType(noEscapingType, escapingType,
3197-
inputSubstType, outputSubstType,
3198-
genericEnv, interfaceSubs,
3199-
/*withoutActuallyEscaping=*/true);
3239+
CanType dynamicSelfType;
3240+
auto type = SGF.buildThunkType(noEscapingType, escapingType,
3241+
inputSubstType, outputSubstType,
3242+
genericEnv, interfaceSubs,
3243+
dynamicSelfType,
3244+
/*withoutActuallyEscaping=*/true);
3245+
assert(!dynamicSelfType && "not implemented");
3246+
return type;
32003247
}
32013248

32023249
static void buildWithoutActuallyEscapingThunkBody(SILGenFunction &SGF) {
@@ -3973,8 +4020,11 @@ SILGenFunction::emitCanonicalFunctionThunk(SILLocation loc, ManagedValue fn,
39734020
// type
39744021
CanType inputSubstType;
39754022
CanType outputSubstType;
4023+
CanType dynamicSelfType;
39764024
auto thunkTy = buildThunkType(nonCanonicalTy, canonicalTy, inputSubstType,
3977-
outputSubstType, genericEnv, interfaceSubs);
4025+
outputSubstType, genericEnv, interfaceSubs,
4026+
dynamicSelfType);
4027+
assert(!dynamicSelfType && "not implemented");
39784028
auto thunk = SGM.getOrCreateReabstractionThunk(thunkTy, nonCanonicalTy,
39794029
canonicalTy, F.isSerialized());
39804030
if (thunk->empty()) {

lib/SILGen/SILGenProlog.cpp

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,22 @@ class EmitBBArguments : public CanTypeVisitor<EmitBBArguments,
103103
// Pop the next parameter info.
104104
auto parameterInfo = parameters.front();
105105
parameters = parameters.slice(1);
106-
assert(
107-
argType
108-
== parent->getParent()->mapTypeIntoContext(
109-
SGF.getSILType(parameterInfo))
110-
&& "argument does not have same type as specified by parameter info");
111-
(void)parameterInfo;
112106

107+
auto paramType = SGF.F.mapTypeIntoContext(SGF.getSILType(parameterInfo));
113108
ManagedValue mv = SGF.B.createInputFunctionArgument(
114-
argType, loc.getAsASTNode<ValueDecl>());
109+
paramType, loc.getAsASTNode<ValueDecl>());
110+
111+
if (argType != paramType) {
112+
// This is a hack to deal with the fact that Self.Type comes in as a
113+
// static metatype, but we have to downcast it to a dynamic Self
114+
// metatype to get the right semantics.
115+
assert(
116+
cast<DynamicSelfType>(
117+
argType.castTo<MetatypeType>().getInstanceType())
118+
.getSelfType()
119+
== paramType.castTo<MetatypeType>().getInstanceType());
120+
mv = SGF.B.createUncheckedBitCast(loc, mv, argType);
121+
}
115122

116123
if (isInOut)
117124
return mv;
@@ -216,7 +223,7 @@ struct ArgumentInitHelper {
216223
assert(ty && "no type?!");
217224

218225
// Create an RValue by emitting destructured arguments into a basic block.
219-
CanType canTy = ty->eraseDynamicSelfType()->getCanonicalType();
226+
CanType canTy = ty->getCanonicalType();
220227
EmitBBArguments argEmitter(SGF, parent, l, parameters);
221228

222229
// Note: inouts of tuples are not exploded, so we bypass visit().
@@ -235,17 +242,6 @@ struct ArgumentInitHelper {
235242

236243
if (vd->isInOut()) {
237244
assert(argrv.getType().isAddress() && "expected inout to be address");
238-
} else if (auto *metatypeTy = ty->getAs<MetatypeType>()) {
239-
// This is a hack to deal with the fact that Self.Type comes in as a
240-
// static metatype, but we have to downcast it to a dynamic Self
241-
// metatype to get the right semantics.
242-
if (metatypeTy->getInstanceType()->is<DynamicSelfType>()) {
243-
auto loweredTy = SGF.getLoweredType(ty);
244-
if (loweredTy != argrv.getType()) {
245-
argrv = ManagedValue::forUnmanaged(
246-
SGF.B.createUncheckedBitCast(loc, argrv.getValue(), loweredTy));
247-
}
248-
}
249245
} else {
250246
assert(vd->isImmutable() && "expected parameter to be immutable!");
251247
// If the variable is immutable, we can bind the value as is.
@@ -320,10 +316,7 @@ static void makeArgument(Type ty, ParamDecl *decl,
320316

321317
void SILGenFunction::bindParameterForForwarding(ParamDecl *param,
322318
SmallVectorImpl<SILValue> &parameters) {
323-
Type type = (param->hasType()
324-
? param->getType()
325-
: F.mapTypeIntoContext(param->getInterfaceType()));
326-
makeArgument(type->eraseDynamicSelfType(), param, parameters, *this);
319+
makeArgument(param->getType(), param, parameters, *this);
327320
}
328321

329322
void SILGenFunction::bindParametersForForwarding(const ParameterList *params,

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -834,7 +834,30 @@ void LifetimeChecker::handleLoadForTypeOfSelfUse(const DIMemoryUse &Use) {
834834
break;
835835
}
836836
assert(valueMetatype);
837-
auto metatypeArgument = load->getFunction()->getSelfMetadataArgument();
837+
SILValue metatypeArgument = load->getFunction()->getSelfMetadataArgument();
838+
839+
// SILFunction parameter types never have a DynamicSelfType, since it only
840+
// makes sense in the context of a given method's body. Since the
841+
// value_metatype instruction might produce a DynamicSelfType we have to
842+
// cast the metatype argument.
843+
//
844+
// FIXME: Semantically, we're "opening" the class metatype here to produce
845+
// the "opened" DynamicSelfType. Ideally it would be modeled as an opened
846+
// archetype associated with the original metatype or class instance value,
847+
// instead of as a "global" type.
848+
auto metatypeSelfType = metatypeArgument->getType()
849+
.castTo<MetatypeType>().getInstanceType();
850+
auto valueSelfType = valueMetatype->getType()
851+
.castTo<MetatypeType>().getInstanceType();
852+
if (metatypeSelfType != valueSelfType) {
853+
assert(metatypeSelfType ==
854+
cast<DynamicSelfType>(valueSelfType).getSelfType());
855+
856+
SILBuilderWithScope B(valueMetatype);
857+
metatypeArgument = B.createUncheckedTrivialBitCast(
858+
valueMetatype->getLoc(), metatypeArgument,
859+
valueMetatype->getType());
860+
}
838861
replaceAllSimplifiedUsesAndErase(valueMetatype, metatypeArgument,
839862
[](SILInstruction*) { });
840863
}

0 commit comments

Comments
 (0)