Skip to content

Commit 5a827a9

Browse files
authored
Merge pull request #21804 from slavapestov/dynamic-self-is-so-broken-5.0
Some fixes for DynamicSelfType [5.0]
2 parents 4469ae9 + 234aabb commit 5a827a9

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
@@ -4056,9 +4056,15 @@ void SILBoxType::Profile(llvm::FoldingSetNodeID &id, SILLayout *Layout,
40564056
Substitutions.profile(id);
40574057
}
40584058

4059-
static RecursiveTypeProperties getRecursivePropertiesOfMap(
4060-
SubstitutionMap subMap) {
4059+
static RecursiveTypeProperties getBoxRecursiveProperties(
4060+
SILLayout *Layout, SubstitutionMap subMap) {
40614061
RecursiveTypeProperties props;
4062+
for (auto &field : Layout->getFields()) {
4063+
auto fieldProps = field.getLoweredType()->getRecursiveProperties();
4064+
fieldProps.removeHasTypeParameter();
4065+
fieldProps.removeHasDependentMember();
4066+
props |= fieldProps;
4067+
}
40624068
for (auto replacementType : subMap.getReplacementTypes()) {
40634069
if (replacementType) props |= replacementType->getRecursiveProperties();
40644070
}
@@ -4067,7 +4073,8 @@ static RecursiveTypeProperties getRecursivePropertiesOfMap(
40674073

40684074
SILBoxType::SILBoxType(ASTContext &C,
40694075
SILLayout *Layout, SubstitutionMap Substitutions)
4070-
: TypeBase(TypeKind::SILBox, &C, getRecursivePropertiesOfMap(Substitutions)),
4076+
: TypeBase(TypeKind::SILBox, &C,
4077+
getBoxRecursiveProperties(Layout, Substitutions)),
40714078
Layout(Layout), Substitutions(Substitutions) {
40724079
assert(Substitutions.isCanonical());
40734080
}

lib/SIL/TypeLowering.cpp

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

17881788
FuncDecl *func = cast<FuncDecl>(vd);
17891789
auto funcTy = cast<AnyFunctionType>(
1790-
func->getInterfaceType()->eraseDynamicSelfType()->getCanonicalType());
1790+
func->getInterfaceType()->getCanonicalType());
17911791
return getFunctionInterfaceTypeWithCaptures(funcTy, func);
17921792
}
17931793

@@ -2099,7 +2099,11 @@ TypeConverter::getLoweredLocalCaptures(AnyFunctionRef fn) {
20992099

21002100
// We're capturing a 'self' value with dynamic 'Self' type;
21012101
// handle it specially.
2102-
if (captureType->getClassOrBoundGenericClass()) {
2102+
//
2103+
// However, only do this if its a 'let'; if the capture is
2104+
// mutable, we're going to be capturing a box or an address.
2105+
if (captureType->getClassOrBoundGenericClass() &&
2106+
capturedVar->isLet()) {
21032107
if (selfCapture)
21042108
selfCapture = selfCapture->mergeFlags(capture);
21052109
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
@@ -1757,6 +1757,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
17571757
CanType &outputSubstType,
17581758
GenericEnvironment *&genericEnv,
17591759
SubstitutionMap &interfaceSubs,
1760+
CanType &dynamicSelfType,
17601761
bool withoutActuallyEscaping=false);
17611762

17621763
//===--------------------------------------------------------------------===//

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);
@@ -2807,11 +2818,14 @@ void ResultPlanner::execute(ArrayRef<SILValue> innerDirectResults,
28072818
/// \param inputSubstType Formal AST type of function value being thunked
28082819
/// \param outputOrigType Abstraction pattern of the thunk
28092820
/// \param outputSubstType Formal AST type of the thunk
2821+
/// \param dynamicSelfType If true, the last parameter is a dummy used to pass
2822+
/// DynamicSelfType metadata
28102823
static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
28112824
AbstractionPattern inputOrigType,
28122825
CanAnyFunctionType inputSubstType,
28132826
AbstractionPattern outputOrigType,
2814-
CanAnyFunctionType outputSubstType) {
2827+
CanAnyFunctionType outputSubstType,
2828+
CanType dynamicSelfType) {
28152829
PrettyStackTraceSILFunction stackTrace("emitting reabstraction thunk in",
28162830
&SGF.F);
28172831
auto thunkType = SGF.F.getLoweredFunctionType();
@@ -2821,6 +2835,11 @@ static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
28212835
SmallVector<ManagedValue, 8> params;
28222836
SGF.collectThunkParams(loc, params);
28232837

2838+
// Ignore the self parameter at the SIL level. IRGen will use it to
2839+
// recover type metadata.
2840+
if (dynamicSelfType)
2841+
params.pop_back();
2842+
28242843
ManagedValue fnValue = params.pop_back_val();
28252844
auto fnType = fnValue.getType().castTo<SILFunctionType>();
28262845
assert(!fnType->isPolymorphic());
@@ -2970,6 +2989,7 @@ CanSILFunctionType SILGenFunction::buildThunkType(
29702989
CanType &outputSubstType,
29712990
GenericEnvironment *&genericEnv,
29722991
SubstitutionMap &interfaceSubs,
2992+
CanType &dynamicSelfType,
29732993
bool withoutActuallyEscaping) {
29742994
assert(!expectedType->isPolymorphic());
29752995
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
@@ -837,7 +837,30 @@ void LifetimeChecker::handleLoadForTypeOfSelfUse(const DIMemoryUse &Use) {
837837
break;
838838
}
839839
assert(valueMetatype);
840-
auto metatypeArgument = load->getFunction()->getSelfMetadataArgument();
840+
SILValue metatypeArgument = load->getFunction()->getSelfMetadataArgument();
841+
842+
// SILFunction parameter types never have a DynamicSelfType, since it only
843+
// makes sense in the context of a given method's body. Since the
844+
// value_metatype instruction might produce a DynamicSelfType we have to
845+
// cast the metatype argument.
846+
//
847+
// FIXME: Semantically, we're "opening" the class metatype here to produce
848+
// the "opened" DynamicSelfType. Ideally it would be modeled as an opened
849+
// archetype associated with the original metatype or class instance value,
850+
// instead of as a "global" type.
851+
auto metatypeSelfType = metatypeArgument->getType()
852+
.castTo<MetatypeType>().getInstanceType();
853+
auto valueSelfType = valueMetatype->getType()
854+
.castTo<MetatypeType>().getInstanceType();
855+
if (metatypeSelfType != valueSelfType) {
856+
assert(metatypeSelfType ==
857+
cast<DynamicSelfType>(valueSelfType).getSelfType());
858+
859+
SILBuilderWithScope B(valueMetatype);
860+
metatypeArgument = B.createUncheckedTrivialBitCast(
861+
valueMetatype->getLoc(), metatypeArgument,
862+
valueMetatype->getType());
863+
}
841864
replaceAllSimplifiedUsesAndErase(valueMetatype, metatypeArgument,
842865
[](SILInstruction*) { });
843866
}

0 commit comments

Comments
 (0)