Skip to content

Commit dd24033

Browse files
authored
Merge pull request swiftlang#63417 from xedin/attach-source-info-to-reflection-metadata-inits
[Sema] RuntimeMetadata: Attach source information to synthesized initializers
2 parents 64a5f48 + 50c1f97 commit dd24033

File tree

2 files changed

+58
-28
lines changed

2 files changed

+58
-28
lines changed

lib/Sema/TypeCheckRuntimeMetadataAttr.cpp

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ static TypeRepr *buildTypeRepr(DeclContext *typeContext,
9797
/// first parameter is always `self` (with or without `inout`).
9898
static ClosureExpr *synthesizeMethodThunk(DeclContext *thunkDC,
9999
NominalTypeDecl *nominal,
100-
FuncDecl *method) {
100+
FuncDecl *method,
101+
SourceLoc thunkLoc) {
101102
auto &ctx = method->getASTContext();
102103

103104
// If this is a method, let's form a thunk so that attribute initializer
@@ -212,17 +213,19 @@ static ClosureExpr *synthesizeMethodThunk(DeclContext *thunkDC,
212213
}
213214

214215
DeclAttributes attrs;
215-
auto *closure = new (ctx) ClosureExpr(
216-
attrs, /*bracketRange=*/SourceRange(),
217-
/*capturedSelf=*/nullptr, ParameterList::create(ctx, closureParams),
218-
/*asyncLoc=*/SourceLoc(),
219-
/*throwsLoc=*/SourceLoc(),
220-
/*arrowLoc=*/SourceLoc(),
221-
/*inLoc=*/SourceLoc(),
222-
/*explicitResultType=*/nullptr, thunkDC);
223-
224-
closure->setBody(BraceStmt::createImplicit(ctx, body),
225-
/*isSingleExpr=*/true);
216+
auto *closure = new (ctx)
217+
ClosureExpr(attrs, /*bracketRange=*/SourceRange(),
218+
/*capturedSelf=*/nullptr,
219+
ParameterList::create(ctx, thunkLoc, closureParams, thunkLoc),
220+
/*asyncLoc=*/SourceLoc(),
221+
/*throwsLoc=*/SourceLoc(),
222+
/*arrowLoc=*/SourceLoc(),
223+
/*inLoc=*/SourceLoc(),
224+
/*explicitResultType=*/nullptr, thunkDC);
225+
226+
closure->setBody(
227+
BraceStmt::create(ctx, thunkLoc, body, thunkLoc, /*implicit=*/true),
228+
/*isSingleExpr=*/true);
226229
closure->setImplicit();
227230

228231
return closure;
@@ -246,6 +249,14 @@ Expr *SynthesizeRuntimeMetadataAttrGenerator::evaluate(
246249

247250
auto *initContext = new (ctx) RuntimeAttributeInitializer(attr, attachedTo);
248251

252+
SourceRange sourceRange;
253+
if (auto *repr = attr->getTypeRepr()) {
254+
sourceRange = repr->getSourceRange();
255+
} else {
256+
sourceRange = SourceRange(
257+
attachedTo->getAttributeInsertionLoc(/*forModifier=*/false));
258+
}
259+
249260
Expr *initArgument = nullptr;
250261
if (auto *nominal = dyn_cast<NominalTypeDecl>(attachedTo)) {
251262
// Registry attributes on protocols are only used for
@@ -254,26 +265,28 @@ Expr *SynthesizeRuntimeMetadataAttrGenerator::evaluate(
254265
return nullptr;
255266

256267
// Form an initializer call passing in the metatype
257-
auto *metatype = TypeExpr::createImplicit(nominal->getDeclaredType(), ctx);
268+
auto *metatype = TypeExpr::createImplicitHack(
269+
sourceRange.Start, nominal->getDeclaredType(), ctx);
258270
initArgument = new (ctx)
259271
DotSelfExpr(metatype, /*dot=*/SourceLoc(), /*self=*/SourceLoc());
260272
} else if (auto *func = dyn_cast<FuncDecl>(attachedTo)) {
261273
if (auto *nominal = func->getDeclContext()->getSelfNominalTypeDecl()) {
262-
initArgument = synthesizeMethodThunk(initContext, nominal, func);
274+
initArgument =
275+
synthesizeMethodThunk(initContext, nominal, func, sourceRange.Start);
263276
} else {
264-
initArgument = new (ctx)
265-
DeclRefExpr({func}, /*Loc=*/DeclNameLoc(), /*implicit=*/true);
277+
initArgument = new (ctx) DeclRefExpr(
278+
{func}, /*Loc=*/DeclNameLoc(sourceRange.Start), /*implicit=*/true);
266279
}
267280
} else {
268281
auto *var = cast<VarDecl>(attachedTo);
269282
assert(!var->isStatic());
270283

271284
auto *keyPath =
272-
KeyPathExpr::createImplicit(ctx, /*backslashLoc=*/SourceLoc(),
285+
KeyPathExpr::createImplicit(ctx, /*backslashLoc=*/sourceRange.Start,
273286
{KeyPathExpr::Component::forProperty(
274287
{var}, var->getValueInterfaceType(),
275-
/*Loc=*/SourceLoc())},
276-
/*endLoc=*/SourceLoc());
288+
/*Loc=*/sourceRange.Start)},
289+
/*endLoc=*/sourceRange.Start);
277290

278291
// Build a type repr for base of the key path, since attribute
279292
// could be attached to an inner type, we need to go up decl
@@ -283,20 +296,13 @@ Expr *SynthesizeRuntimeMetadataAttrGenerator::evaluate(
283296
initArgument = keyPath;
284297
}
285298

286-
SourceRange sourceRange;
287-
if (auto *repr = attr->getTypeRepr()) {
288-
sourceRange = repr->getSourceRange();
289-
} else {
290-
sourceRange = SourceRange(
291-
attachedTo->getAttributeInsertionLoc(/*forModifier=*/false));
292-
}
293-
294299
auto typeExpr =
295300
TypeExpr::createImplicitHack(sourceRange.Start, attrType, ctx);
296301

297302
// Add the initializer argument at the front of the argument list
298303
SmallVector<Argument, 4> newArgs;
299-
newArgs.push_back({/*loc=*/SourceLoc(), ctx.Id_attachedTo, initArgument});
304+
newArgs.push_back(
305+
{/*loc=*/sourceRange.Start, ctx.Id_attachedTo, initArgument});
300306
if (auto *attrArgs = attr->getArgs())
301307
newArgs.append(attrArgs->begin(), attrArgs->end());
302308

test/type/runtime_discoverable_attrs.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,3 +349,27 @@ protocol OptedOutProtoWithSuperclass : BaseClass {} // Ok
349349
@available(*, unavailable)
350350
@Flag
351351
extension OptedOutProtoWithSuperclass {}
352+
353+
@runtimeMetadata
354+
struct FlagForFailures {
355+
init(attachedTo: Int.Type) {}
356+
init<T>(attachedTo: KeyPath<Int, T>) {}
357+
init(attachedTo: (Int) -> Void, _: String) {}
358+
}
359+
360+
@FlagForFailures // expected-error {{cannot convert value of type 'InvalidMembersTests.Type' to expected argument type 'Int.Type'}}
361+
struct InvalidMembersTests {
362+
@FlagForFailures var x: Int
363+
// expected-error@-1 {{cannot convert value of type 'KeyPath<InvalidMembersTests, Int>' to expected argument type 'KeyPath<Int, Int>'}}
364+
// expected-note@-2 {{arguments to generic parameter 'Root' ('InvalidMembersTests' and 'Int') are expected to be equal}}
365+
366+
@FlagForFailures("") static func testStatic() {}
367+
// expected-error@-1 {{cannot convert value of type '(InvalidMembersTests.Type) -> ()' to expected argument type '(Int) -> Void'}}
368+
369+
@FlagForFailures(42) func testInst() {}
370+
// expected-error@-1 {{cannot convert value of type '(InvalidMembersTests) -> ()' to expected argument type '(Int) -> Void'}}
371+
// expected-error@-2:20 {{cannot convert value of type 'Int' to expected argument type 'String'}}
372+
}
373+
374+
@FlagForFailures("global") func testGlobalInvalid() {}
375+
// expected-error@-1 {{cannot convert value of type '() -> ()' to expected argument type '(Int) -> Void'}}

0 commit comments

Comments
 (0)