Skip to content

Commit 5bd4341

Browse files
committed
[Sema] RuntimeMetadata: Make sure that inferred attributes have source information
If an attribute is inferred from a protocol conformance it won't have any source information, in such cases let's determine where an attribute could have been inserted if it was spelled explicitly and use that location in a synthesized initializer call. Resolves: rdar://103938899
1 parent 6d657c9 commit 5bd4341

File tree

3 files changed

+97
-6
lines changed

3 files changed

+97
-6
lines changed

lib/Sema/TypeCheckRuntimeMetadataAttr.cpp

+11-6
Original file line numberDiff line numberDiff line change
@@ -283,20 +283,25 @@ Expr *SynthesizeRuntimeMetadataAttrGenerator::evaluate(
283283
initArgument = keyPath;
284284
}
285285

286-
auto reprRange = SourceRange();
287-
if (auto *repr = attr->getTypeRepr())
288-
reprRange = repr->getSourceRange();
286+
SourceRange sourceRange;
287+
if (auto *repr = attr->getTypeRepr()) {
288+
sourceRange = repr->getSourceRange();
289+
} else {
290+
sourceRange = SourceRange(
291+
attachedTo->getAttributeInsertionLoc(/*forModifier=*/false));
292+
}
289293

290-
auto typeExpr = TypeExpr::createImplicitHack(reprRange.Start, attrType, ctx);
294+
auto typeExpr =
295+
TypeExpr::createImplicitHack(sourceRange.Start, attrType, ctx);
291296

292297
// Add the initializer argument at the front of the argument list
293298
SmallVector<Argument, 4> newArgs;
294299
newArgs.push_back({/*loc=*/SourceLoc(), ctx.Id_attachedTo, initArgument});
295300
if (auto *attrArgs = attr->getArgs())
296301
newArgs.append(attrArgs->begin(), attrArgs->end());
297302

298-
ArgumentList *argList = ArgumentList::createImplicit(ctx, reprRange.Start,
299-
newArgs, reprRange.End);
303+
ArgumentList *argList = ArgumentList::createImplicit(
304+
ctx, sourceRange.Start, newArgs, sourceRange.End);
300305
Expr *init = CallExpr::createImplicit(ctx, typeExpr, argList);
301306

302307
// result of generator is an optional always.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@runtimeMetadata
2+
public struct Ignore {
3+
public init<T>(attachedTo: T,
4+
fileID: String = #fileID,
5+
line: Int = #line,
6+
column: Int = #column) {}
7+
}
8+
9+
@Ignore
10+
public protocol Ignorable {}

test/SILGen/runtime_attributes.swift

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -enable-experimental-feature RuntimeDiscoverableAttrs -emit-module -o %t -enable-library-evolution %S/Inputs/runtime_metadata_defs.swift
3+
4+
// This uses '-primary-file' to ensure we're conservative with lazy SIL emission.
5+
// RUN: %target-swift-emit-silgen -enable-experimental-feature RuntimeDiscoverableAttrs -primary-file %s -I %t | %FileCheck %s
6+
7+
// REQUIRES: asserts
8+
// REQUIRES: concurrency
9+
10+
import runtime_metadata_defs
11+
12+
/// Test that generator has source locations for both explicit and inferred attributes.
13+
14+
// CHECK-LABEL: sil hidden [runtime_accessible] [ossa] @$s18runtime_attributes4TestAaBVmvpfa0A14_metadata_defs6Ignore : $@convention(thin) () -> @out Optional<Ignore>
15+
// CHECK: [[FILE_ID:%.*]] = string_literal utf8 "runtime_attributes/runtime_attributes.swift"
16+
// CHECK: [[STRING_INIT:%.*]] = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC
17+
// CHECK-NEXT: [[FILE_STR:%.*]] = apply [[STRING_INIT]]([[FILE_ID]], {{.*}})
18+
// CHECK: [[LINE_RAW:%.*]] = integer_literal $Builtin.IntLiteral, 26
19+
// CHECK: [[INT_INIT:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC
20+
// CHECK-NEXT: [[LINE:%.*]] = apply [[INT_INIT]]([[LINE_RAW]], {{.*}})
21+
// CHECK: [[COLUMN_RAW:%.*]] = integer_literal $Builtin.IntLiteral, 1
22+
// CHECK: [[INT_INIT:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC
23+
// CHECK-NEXT: [[COLUMN:%.*]] = apply [[INT_INIT]]([[COLUMN_RAW]], {{.*}})
24+
// CHECK: [[IGNORE_INIT:%.*]] = function_ref @$s21runtime_metadata_defs6IgnoreV10attachedTo6fileID4line6columnACx_SSS2itclufC
25+
// CHECK-NEXT: {{.*}} = apply [[IGNORE_INIT]]<Test.Type>({{.*}}, {{.*}}, [[FILE_STR]], [[LINE]], [[COLUMN]], {{.*}})
26+
struct Test : Ignorable {}
27+
28+
// CHECK-LABEL: sil hidden [runtime_accessible] [ossa] @$s18runtime_attributes8globalFnyycvpfa0A14_metadata_defs6Ignore : $@convention(thin) () -> @out Optional<Ignore>
29+
// CHECK: {{.*}} = string_literal utf8 "runtime_attributes/runtime_attributes.swift"
30+
// CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 34
31+
// CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 2
32+
// CHECK: [[IGNORE_INIT:%.*]] = function_ref @$s21runtime_metadata_defs6IgnoreV10attachedTo6fileID4line6columnACx_SSS2itclufC
33+
// CHECK-NEXT: {{.*}} = apply [[IGNORE_INIT]]<() -> ()>({{.*}})
34+
@Ignore func globalFn() {}
35+
36+
struct MemberTests {
37+
// CHECK-LABEL: sil hidden [runtime_accessible] [ossa] @$s18runtime_attributes11MemberTestsV1xSivpfa0A14_metadata_defs6Ignore : $@convention(thin) () -> @out Optional<Ignore>
38+
// CHECK: {{.*}} = string_literal utf8 "runtime_attributes/runtime_attributes.swift"
39+
// CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 43
40+
// CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 4
41+
// CHECK: [[IGNORE_INIT:%.*]] = function_ref @$s21runtime_metadata_defs6IgnoreV10attachedTo6fileID4line6columnACx_SSS2itclufC
42+
// CHECK-NEXT: {{.*}} = apply [[IGNORE_INIT]]<WritableKeyPath<MemberTests, Int>>({{.*}})
43+
@Ignore var x: Int = 42
44+
45+
// CHECK-LABEL: sil hidden [runtime_accessible] [ossa] @$s18runtime_attributes11MemberTestsV6instFn_1xSSSi_SaySiGtcvpfa0A14_metadata_defs6Ignore : $@convention(thin) () -> @out Optional<Ignore>
46+
// CHECK: {{.*}} = string_literal utf8 "runtime_attributes/runtime_attributes.swift"
47+
// CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 51
48+
// CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 4
49+
// CHECK: [[IGNORE_INIT:%.*]] = function_ref @$s21runtime_metadata_defs6IgnoreV10attachedTo6fileID4line6columnACx_SSS2itclufC
50+
// CHECK-NEXT: {{.*}} = apply [[IGNORE_INIT]]<(MemberTests, Int, [Int]) -> String>({{.*}})
51+
@Ignore func instFn(_: Int, x: [Int]) -> String { "" }
52+
53+
// CHECK-LABEL: sil hidden [runtime_accessible] [ossa] @$s18runtime_attributes11MemberTestsV8staticFn_1ySi_SStSS_SiztcvpZfa0A14_metadata_defs6Ignore : $@convention(thin) () -> @out Optional<Ignore>
54+
// CHECK: {{.*}} = string_literal utf8 "runtime_attributes/runtime_attributes.swift"
55+
// CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 59
56+
// CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 4
57+
// CHECK: [[IGNORE_INIT:%.*]] = function_ref @$s21runtime_metadata_defs6IgnoreV10attachedTo6fileID4line6columnACx_SSS2itclufC
58+
// CHECK-NEXT: {{.*}} = apply [[IGNORE_INIT]]<(MemberTests.Type, String, inout Int) -> (Int, String)>({{.*}})
59+
@Ignore static func staticFn(_ x: String, y: inout Int) -> (Int, String) { (42, "") }
60+
61+
// CHECK-LABEL: sil hidden [runtime_accessible] [ossa] @$s18runtime_attributes11MemberTestsV10mutatingFnSiycvpfa0A14_metadata_defs6Ignore : $@convention(thin) () -> @out Optional<Ignore>
62+
// CHECK: {{.*}} = string_literal utf8 "runtime_attributes/runtime_attributes.swift"
63+
// CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 67
64+
// CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 4
65+
// CHECK: [[IGNORE_INIT:%.*]] = function_ref @$s21runtime_metadata_defs6IgnoreV10attachedTo6fileID4line6columnACx_SSS2itclufC
66+
// CHECK-NEXT: {{.*}} = apply [[IGNORE_INIT]]<(inout MemberTests) -> Int>({{.*}})
67+
@Ignore mutating func mutatingFn() -> Int { 42 }
68+
69+
// CHECK-LABEL: sil hidden [runtime_accessible] [ossa] @$s18runtime_attributes11MemberTestsV05asyncC0SiyYaKcvpfa0A14_metadata_defs6Ignore : $@convention(thin) () -> @out Optional<Ignore>
70+
// CHECK: {{.*}} = string_literal utf8 "runtime_attributes/runtime_attributes.swift"
71+
// CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 75
72+
// CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 4
73+
// CHECK: [[IGNORE_INIT:%.*]] = function_ref @$s21runtime_metadata_defs6IgnoreV10attachedTo6fileID4line6columnACx_SSS2itclufC
74+
// CHECK-NEXT: {{.*}} = apply [[IGNORE_INIT]]<(MemberTests) async throws -> Int>({{.*}})
75+
@Ignore func asyncMember() async throws -> Int { 42 }
76+
}

0 commit comments

Comments
 (0)