Skip to content

Commit d6ed370

Browse files
authored
Merge pull request swiftlang#62818 from xedin/runtime-metadata-thunks-should-have-metatatype-for-static-methods
[Sema] RuntimeMetadata: Require "self" for both static and instance methods
2 parents df00577 + 099c643 commit d6ed370

File tree

3 files changed

+44
-28
lines changed

3 files changed

+44
-28
lines changed

lib/Sema/TypeCheckRuntimeMetadataAttr.cpp

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ ValueDecl::getRuntimeDiscoverableAttributeGenerator(CustomAttr *attr) const {
4848
return std::make_pair(body, init->getType()->mapTypeOutOfContext());
4949
}
5050

51-
static TypeRepr *buildTypeRepr(DeclContext *typeContext) {
51+
static TypeRepr *buildTypeRepr(DeclContext *typeContext,
52+
bool forMetatype = false) {
5253
assert(typeContext->isTypeContext());
5354

5455
SmallVector<ComponentIdentTypeRepr *, 2> components;
@@ -77,10 +78,17 @@ static TypeRepr *buildTypeRepr(DeclContext *typeContext) {
7778
// Reverse the components to form a valid outer-to-inner name sequence.
7879
std::reverse(components.begin(), components.end());
7980

80-
if (components.size() == 1)
81-
return components.front();
81+
TypeRepr *typeRepr = nullptr;
82+
if (components.size() == 1) {
83+
typeRepr = components.front();
84+
} else {
85+
typeRepr = CompoundIdentTypeRepr::create(ctx, components);
86+
}
8287

83-
return CompoundIdentTypeRepr::create(ctx, components);
88+
if (forMetatype)
89+
return new (ctx) MetatypeTypeRepr(typeRepr, /*MetaLoc=*/SourceLoc());
90+
91+
return typeRepr;
8492
}
8593

8694
/// Synthesizes a closure thunk that forwards all of the arguments
@@ -98,22 +106,22 @@ static ClosureExpr *synthesizeMethodThunk(DeclContext *thunkDC,
98106

99107
SmallVector<ParamDecl *, 4> closureParams;
100108

101-
NullablePtr<ParamDecl> selfParam;
102-
if (!method->isStatic()) {
103-
auto *self = ParamDecl::createImplicit(
104-
ctx,
105-
/*argumentName=*/Identifier(),
106-
/*parameterName=*/ctx.Id_self,
107-
/*type=*/nominal->getDeclaredInterfaceType(), thunkDC,
108-
method->isMutating() ? ParamSpecifier::InOut : ParamSpecifier::Default);
109-
109+
ParamDecl *selfParam = ParamDecl::createImplicit(
110+
ctx,
111+
/*argumentName=*/Identifier(),
112+
/*parameterName=*/ctx.Id_self,
113+
/*type=*/
114+
method->isStatic() ? nominal->getInterfaceType()
115+
: nominal->getDeclaredInterfaceType(),
116+
thunkDC,
117+
method->isMutating() ? ParamSpecifier::InOut : ParamSpecifier::Default);
118+
{
110119
// This is very important for the solver, without a type repr
111120
// it would create a type variable and attempt infer the type
112121
// from the body.
113-
self->setTypeRepr(buildTypeRepr(nominal));
122+
selfParam->setTypeRepr(buildTypeRepr(nominal, method->isStatic()));
114123

115-
closureParams.push_back(self);
116-
selfParam = self;
124+
closureParams.push_back(selfParam);
117125
}
118126

119127
if (funcParams) {
@@ -139,14 +147,9 @@ static ClosureExpr *synthesizeMethodThunk(DeclContext *thunkDC,
139147
// return self.<func>(<arguments>)
140148
SmallVector<ASTNode, 2> body;
141149
{
142-
NullablePtr<Expr> baseExpr;
143-
if (method->isStatic()) {
144-
baseExpr =
145-
TypeExpr::createImplicit(nominal->getDeclaredInterfaceType(), ctx);
146-
} else {
147-
baseExpr = new (ctx) DeclRefExpr({selfParam.get()}, /*Loc=*/DeclNameLoc(),
148-
/*implicit=*/true);
149-
}
150+
NullablePtr<Expr> baseExpr =
151+
new (ctx) DeclRefExpr({selfParam}, /*Loc=*/DeclNameLoc(),
152+
/*implicit=*/true);
150153

151154
auto *memberRef = new (ctx) MemberRefExpr(
152155
baseExpr.get(), /*dotLoc=*/SourceLoc(), {method}, /*loc=*/DeclNameLoc(),
@@ -157,10 +160,9 @@ static ClosureExpr *synthesizeMethodThunk(DeclContext *thunkDC,
157160
for (unsigned i = 0, n = funcParams->size(); i != n; ++i) {
158161
const auto *param = funcParams->get(i);
159162

160-
Expr *argExpr = new (ctx)
161-
DeclRefExpr({closureParams[method->isStatic() ? i : i + 1]},
162-
/*Loc=*/DeclNameLoc(),
163-
/*implicit=*/true);
163+
Expr *argExpr = new (ctx) DeclRefExpr({closureParams[i + 1]},
164+
/*Loc=*/DeclNameLoc(),
165+
/*implicit=*/true);
164166

165167
if (param->isInOut()) {
166168
argExpr = new (ctx) InOutExpr(/*operLoc=*/SourceLoc(), argExpr,

test/IRGen/runtime_attributes.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ func test_local_type_with_protocol_conformance() {
294294
struct FlagForInnerMethods<Result> {
295295
init(attachedTo: () -> Result) {}
296296
init<T>(attachedTo: (T) -> Result) {}
297+
init<T>(attachedTo: (T.Type) -> Result) {}
297298
init<T>(attachedTo: (inout T) -> Result) {}
298299
init<T>(attachedTo: (inout T, String, inout Int) -> Result) {}
299300
}

test/type/runtime_discoverable_attrs.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,16 @@ actor TestActor {
212212
func globalAsyncFn() async -> [String] {
213213
return []
214214
}
215+
216+
@runtimeMetadata
217+
struct FlagForStaticFuncs {
218+
init<T>(attachedTo: (T.Type) -> Void) {}
219+
init<T>(attachedTo: (T.Type, Int.Type) -> Void) {}
220+
init<T>(attachedTo: (T.Type, inout [String], Int) -> Void) {}
221+
}
222+
223+
struct TestStaticFuncs {
224+
@FlagForStaticFuncs static func test0() {}
225+
@FlagForStaticFuncs static func test1(_: Int.Type) {}
226+
@FlagForStaticFuncs static func test2(_: inout [String], x: Int) {}
227+
}

0 commit comments

Comments
 (0)