Skip to content

Commit dc7fc43

Browse files
committed
[ASTGen] Generate LifetimeAttr
1 parent c2e36de commit dc7fc43

File tree

6 files changed

+295
-11
lines changed

6 files changed

+295
-11
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class Fingerprint;
4848
class Identifier;
4949
class IfConfigClauseRangeInfo;
5050
struct LabeledStmtInfo;
51+
struct LifetimeDescriptor;
5152
enum class MacroRole : uint32_t;
5253
class MacroIntroducedDeclName;
5354
enum class MacroIntroducedDeclNameKind;
@@ -964,6 +965,80 @@ BridgedInlineAttr BridgedInlineAttr_createParsed(BridgedASTContext cContext,
964965
BridgedSourceRange cRange,
965966
BridgedInlineKind cKind);
966967

968+
enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedParsedLifetimeDependenceKind {
969+
BridgedParsedLifetimeDependenceKindDefault,
970+
BridgedParsedLifetimeDependenceKindScope,
971+
BridgedParsedLifetimeDependenceKindInherit,
972+
};
973+
974+
class BridgedLifetimeDescriptor {
975+
union Value {
976+
BridgedIdentifier name;
977+
unsigned index;
978+
nullptr_t null;
979+
980+
Value(BridgedIdentifier name) : name(name) {}
981+
Value(unsigned index) : index(index) {}
982+
Value() : null() {}
983+
} value;
984+
985+
enum DescriptorKind {
986+
Named,
987+
Ordered,
988+
Self,
989+
} kind;
990+
991+
BridgedParsedLifetimeDependenceKind dependenceKind;
992+
BridgedSourceLoc loc;
993+
994+
BridgedLifetimeDescriptor(Value value, DescriptorKind kind,
995+
BridgedParsedLifetimeDependenceKind dependenceKind,
996+
BridgedSourceLoc loc)
997+
: value(value), kind(kind), dependenceKind(dependenceKind), loc(loc) {}
998+
999+
public:
1000+
SWIFT_NAME("forNamed(_:dependenceKind:loc:)")
1001+
static BridgedLifetimeDescriptor
1002+
forNamed(BridgedIdentifier name,
1003+
BridgedParsedLifetimeDependenceKind dependenceKind,
1004+
BridgedSourceLoc loc) {
1005+
return BridgedLifetimeDescriptor(name, DescriptorKind::Named,
1006+
dependenceKind, loc);
1007+
}
1008+
SWIFT_NAME("forOrdered(_:dependenceKind:loc:)")
1009+
static BridgedLifetimeDescriptor
1010+
forOrdered(size_t index, BridgedParsedLifetimeDependenceKind dependenceKind,
1011+
BridgedSourceLoc loc) {
1012+
return BridgedLifetimeDescriptor(index, DescriptorKind::Ordered,
1013+
dependenceKind, loc);
1014+
}
1015+
SWIFT_NAME("forSelf(dependenceKind:loc:)")
1016+
static BridgedLifetimeDescriptor
1017+
forSelf(BridgedParsedLifetimeDependenceKind dependenceKind,
1018+
BridgedSourceLoc loc) {
1019+
return BridgedLifetimeDescriptor({}, DescriptorKind::Self, dependenceKind,
1020+
loc);
1021+
}
1022+
1023+
swift::LifetimeDescriptor unbridged();
1024+
};
1025+
1026+
SWIFT_NAME("BridgedLifetimeEntry.createParsed(_:range:sources:)")
1027+
BridgedLifetimeEntry
1028+
BridgedLifetimeEntry_createParsed(BridgedASTContext cContext,
1029+
BridgedSourceRange cRange,
1030+
BridgedArrayRef cSources);
1031+
1032+
SWIFT_NAME("BridgedLifetimeEntry.createParsed(_:range:sources:target:)")
1033+
BridgedLifetimeEntry BridgedLifetimeEntry_createParsed(
1034+
BridgedASTContext cContext, BridgedSourceRange cRange,
1035+
BridgedArrayRef cSources, BridgedLifetimeDescriptor cTarget);
1036+
1037+
SWIFT_NAME("BridgedLifetimeAttr.createParsed(_:atLoc:range:entry:)")
1038+
BridgedLifetimeAttr BridgedLifetimeAttr_createParsed(
1039+
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
1040+
BridgedSourceRange cRange, BridgedLifetimeEntry cEntry);
1041+
9671042
enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedMacroSyntax {
9681043
BridgedMacroSyntaxFreestanding,
9691044
BridgedMacroSyntaxAttached,

include/swift/AST/ASTBridgingWrappers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ AST_BRIDGING_WRAPPER_NULLABLE(ArgumentList)
115115
AST_BRIDGING_WRAPPER_NULLABLE(AvailabilitySpec)
116116
AST_BRIDGING_WRAPPER_CONST_NONNULL(AvailabilityMacroMap)
117117
AST_BRIDGING_WRAPPER_NONNULL(PoundAvailableInfo)
118+
AST_BRIDGING_WRAPPER_NONNULL(LifetimeEntry)
118119

119120
// Non-AST types to generate wrappers for.
120121
AST_BRIDGING_WRAPPER_NULLABLE(DiagnosticEngine)

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5120,7 +5120,12 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
51205120
}
51215121
void visitLifetimeAttr(LifetimeAttr *Attr, Label label) {
51225122
printCommon(Attr, "lifetime_attr", label);
5123-
// TODO: Implement.
5123+
// FIXME: Improve, more detailed info.
5124+
printFieldRaw(
5125+
[&](raw_ostream &out) {
5126+
out << " " << Attr->getLifetimeEntry()->getString() << " ";
5127+
},
5128+
Label::optional("lifetime_entry"));
51245129
printFoot();
51255130
}
51265131
void visitMacroRoleAttr(MacroRoleAttr *Attr, Label label) {

lib/AST/Bridging/DeclAttributeBridging.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,73 @@ BridgedInlineAttr BridgedInlineAttr_createParsed(BridgedASTContext cContext,
360360
InlineAttr(cAtLoc.unbridged(), cRange.unbridged(), unbridged(cKind));
361361
}
362362

363+
static swift::ParsedLifetimeDependenceKind
364+
unbridged(BridgedParsedLifetimeDependenceKind kind) {
365+
switch (kind) {
366+
case BridgedParsedLifetimeDependenceKindDefault:
367+
return swift::ParsedLifetimeDependenceKind::Default;
368+
case BridgedParsedLifetimeDependenceKindScope:
369+
return swift::ParsedLifetimeDependenceKind::Scope;
370+
case BridgedParsedLifetimeDependenceKindInherit:
371+
return swift::ParsedLifetimeDependenceKind::Inherit;
372+
}
373+
llvm_unreachable("unhandled enum value");
374+
}
375+
376+
swift::LifetimeDescriptor BridgedLifetimeDescriptor::unbridged() {
377+
switch (kind) {
378+
case DescriptorKind::Named:
379+
return LifetimeDescriptor::forNamed(value.name.unbridged().str(),
380+
::unbridged(dependenceKind),
381+
loc.unbridged());
382+
case DescriptorKind::Ordered:
383+
return LifetimeDescriptor::forOrdered(
384+
value.index, ::unbridged(dependenceKind), loc.unbridged());
385+
case DescriptorKind::Self:
386+
return LifetimeDescriptor::forSelf(::unbridged(dependenceKind),
387+
loc.unbridged());
388+
}
389+
llvm_unreachable("unhandled enum value");
390+
}
391+
392+
static BridgedLifetimeEntry BridgedLifetimeEntry_createParsedImpl(
393+
BridgedASTContext cContext, BridgedSourceRange cRange,
394+
BridgedArrayRef cSources,
395+
std::optional<BridgedLifetimeDescriptor> cTarget) {
396+
SmallVector<LifetimeDescriptor> sources;
397+
for (auto cSource : cSources.unbridged<BridgedLifetimeDescriptor>())
398+
sources.push_back(cSource.unbridged());
399+
std::optional<LifetimeDescriptor> target;
400+
if (cTarget)
401+
target = cTarget->unbridged();
402+
403+
return LifetimeEntry::create(cContext.unbridged(), cRange.Start.unbridged(),
404+
cRange.End.unbridged(), sources, target);
405+
}
406+
407+
BridgedLifetimeEntry
408+
BridgedLifetimeEntry_createParsed(BridgedASTContext cContext,
409+
BridgedSourceRange cRange,
410+
BridgedArrayRef cSources) {
411+
return BridgedLifetimeEntry_createParsedImpl(cContext, cRange, cSources,
412+
std::nullopt);
413+
}
414+
415+
BridgedLifetimeEntry BridgedLifetimeEntry_createParsed(
416+
BridgedASTContext cContext, BridgedSourceRange cRange,
417+
BridgedArrayRef cSources, BridgedLifetimeDescriptor cTarget) {
418+
return BridgedLifetimeEntry_createParsedImpl(cContext, cRange, cSources,
419+
cTarget);
420+
}
421+
422+
BridgedLifetimeAttr BridgedLifetimeAttr_createParsed(
423+
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
424+
BridgedSourceRange cRange, BridgedLifetimeEntry cEntry) {
425+
return LifetimeAttr::create(cContext.unbridged(), cAtLoc.unbridged(),
426+
cRange.unbridged(), /*implicit=*/false,
427+
cEntry.unbridged());
428+
}
429+
363430
BridgedMacroRole BridgedMacroRole_fromString(BridgedStringRef str) {
364431
// Match the role string to the known set of roles.
365432
auto role =

lib/ASTGen/Sources/ASTGen/DeclAttrs.swift

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ extension ASTGenVisitor {
146146
case .inline:
147147
return handle(self.generateInlineAttr(attribute: node)?.asDeclAttribute)
148148
case .lifetime:
149-
fatalError("unimplemented")
149+
return handle(self.generateLifetimeAttr(attribute: node)?.asDeclAttribute)
150150
case .macroRole:
151151
return handle(self.generateMacroRoleAttr(attribute: node, attrName: attrName)?.asDeclAttribute)
152152
case .nonSendable:
@@ -880,6 +880,128 @@ extension ASTGenVisitor {
880880
)
881881
}
882882

883+
func generateLifetimeDescriptor(nameToken node: TokenSyntax, lifetimeDependenceKind: BridgedParsedLifetimeDependenceKind = .default) -> BridgedLifetimeDescriptor {
884+
let ident = self.generateIdentifier(node)
885+
let loc = self.generateSourceLoc(node)
886+
if ident == ctx.id_self {
887+
return .forSelf(
888+
dependenceKind: lifetimeDependenceKind,
889+
loc: loc
890+
)
891+
} else {
892+
return .forNamed(
893+
ident,
894+
dependenceKind: lifetimeDependenceKind,
895+
loc: loc
896+
);
897+
}
898+
}
899+
900+
func generateLifetimeDescriptor(expr node: ExprSyntax) -> BridgedLifetimeDescriptor? {
901+
let lifetimeDependenceKind: BridgedParsedLifetimeDependenceKind
902+
let descriptorExpr: ExprSyntax
903+
if let copyExpr = node.as(CopyExprSyntax.self) {
904+
lifetimeDependenceKind = .inherit
905+
descriptorExpr = copyExpr.expression
906+
} else if let borrowExpr = node.as(BorrowExprSyntax.self) {
907+
lifetimeDependenceKind = .scope
908+
descriptorExpr = borrowExpr.expression
909+
} else {
910+
lifetimeDependenceKind = .default
911+
descriptorExpr = node
912+
}
913+
914+
let loc = self.generateSourceLoc(descriptorExpr)
915+
if
916+
let declRefExpr = descriptorExpr.as(DeclReferenceExprSyntax.self),
917+
declRefExpr.argumentNames == nil
918+
{
919+
return generateLifetimeDescriptor(
920+
nameToken: declRefExpr.baseName,
921+
lifetimeDependenceKind: lifetimeDependenceKind
922+
)
923+
}
924+
925+
if let index = descriptorExpr.as(IntegerLiteralExprSyntax.self)?.representedLiteralValue {
926+
return .forOrdered(
927+
index,
928+
dependenceKind: lifetimeDependenceKind,
929+
loc: loc
930+
)
931+
}
932+
933+
// TODO: Diangose
934+
fatalError("expected identifier, 'self', or integer in @lifetime")
935+
}
936+
937+
func generateLifetimeEntry(attribute node: AttributeSyntax) -> BridgedLifetimeEntry? {
938+
self.generateWithLabeledExprListArguments(attribute: node) { args in
939+
guard !args.isEmpty else {
940+
// TODO: Diagnose
941+
fatalError("expected arguments in @lifetime attribute")
942+
}
943+
944+
var target: BridgedLifetimeDescriptor? = nil
945+
var sources: [BridgedLifetimeDescriptor] = []
946+
var first = true
947+
while let arg = args.popFirst() {
948+
if first {
949+
if let targetToken = arg.label {
950+
target = self.generateLifetimeDescriptor(nameToken: targetToken)
951+
}
952+
} else {
953+
if arg.label != nil {
954+
// TODO: Diagnose.
955+
fatalError("invalid argument label in @lifetime attribute")
956+
}
957+
first = false
958+
}
959+
if let src = self.generateLifetimeDescriptor(expr: arg.expression) {
960+
sources.append(src)
961+
}
962+
}
963+
964+
if let target {
965+
return .createParsed(
966+
self.ctx,
967+
range: self.generateAttrSourceRange(node),
968+
sources: sources.lazy.bridgedArray(in: self),
969+
target: target
970+
)
971+
} else {
972+
return .createParsed(
973+
self.ctx,
974+
range: self.generateAttrSourceRange(node),
975+
sources: sources.lazy.bridgedArray(in: self)
976+
)
977+
}
978+
}
979+
}
980+
981+
/// E.g.
982+
/// ```
983+
/// @lifetime(src1, src2)
984+
/// @lifetime(target: borrow src1, copy src2)
985+
/// @lifetime(2)
986+
/// @lifetime(self)
987+
/// ```
988+
func generateLifetimeAttr(attribute node: AttributeSyntax) -> BridgedLifetimeAttr? {
989+
guard self.ctx.langOptsHasFeature(.LifetimeDependence) else {
990+
// TODO: Diagnose
991+
fatalError("@lifetime attribute requires 'LifetimeDependence' feature")
992+
}
993+
guard let entry = self.generateLifetimeEntry(attribute: node) else {
994+
// TODO: Diagnose?
995+
return nil
996+
}
997+
return .createParsed(
998+
self.ctx,
999+
atLoc: self.generateSourceLoc(node.atSign),
1000+
range: self.generateAttrSourceRange(node),
1001+
entry: entry
1002+
)
1003+
}
1004+
8831005
func generateMacroIntroducedDeclNameKind(declReferenceExpr node: DeclReferenceExprSyntax) -> BridgedMacroIntroducedDeclNameKind? {
8841006
if node.argumentNames != nil {
8851007
// TODO: Diagnose

test/ASTGen/attrs.swift

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
// RUN: %empty-directory(%t)
22

3-
// RUN: %target-swift-frontend-dump-parse -disable-availability-checking \
4-
// RUN: -enable-experimental-feature SymbolLinkageMarkers \
3+
// RUN: %target-swift-frontend-dump-parse \
54
// RUN: -enable-experimental-feature ABIAttribute \
65
// RUN: -enable-experimental-feature Extern \
6+
// RUN: -enable-experimental-feature LifetimeDependence \
77
// RUN: -enable-experimental-feature NonIsolatedAsyncInheritsIsolationFromContext \
8+
// RUN: -enable-experimental-feature SymbolLinkageMarkers \
89
// RUN: -enable-experimental-move-only \
910
// RUN: -enable-experimental-feature ParserASTGen \
1011
// RUN: | %sanitize-address > %t/astgen.ast
1112

12-
// RUN: %target-swift-frontend-dump-parse -disable-availability-checking \
13-
// RUN: -enable-experimental-feature SymbolLinkageMarkers \
13+
// RUN: %target-swift-frontend-dump-parse \
1414
// RUN: -enable-experimental-feature ABIAttribute \
1515
// RUN: -enable-experimental-feature Extern \
16+
// RUN: -enable-experimental-feature LifetimeDependence \
1617
// RUN: -enable-experimental-feature NonIsolatedAsyncInheritsIsolationFromContext \
18+
// RUN: -enable-experimental-feature SymbolLinkageMarkers \
1719
// RUN: -enable-experimental-move-only \
1820
// RUN: | %sanitize-address > %t/cpp-parser.ast
1921

@@ -22,19 +24,21 @@
2224
// RUN: %target-typecheck-verify-swift \
2325
// RUN: -module-abi-name ASTGen \
2426
// RUN: -enable-experimental-feature ParserASTGen \
25-
// RUN: -enable-experimental-feature SymbolLinkageMarkers \
2627
// RUN: -enable-experimental-feature ABIAttribute \
2728
// RUN: -enable-experimental-feature Extern \
28-
// RUN: -enable-experimental-move-only \
29-
// RUN: -enable-experimental-feature NonIsolatedAsyncInheritsIsolationFromContext
29+
// RUN: -enable-experimental-feature LifetimeDependence \
30+
// RUN: -enable-experimental-feature NonIsolatedAsyncInheritsIsolationFromContext \
31+
// RUN: -enable-experimental-feature SymbolLinkageMarkers \
32+
// RUN: -enable-experimental-move-only
3033

3134
// REQUIRES: executable_test
3235
// REQUIRES: swift_swift_parser
33-
// REQUIRES: swift_feature_SymbolLinkageMarkers
34-
// REQUIRES: swift_feature_Extern
3536
// REQUIRES: swift_feature_ParserASTGen
3637
// REQUIRES: swift_feature_ABIAttribute
38+
// REQUIRES: swift_feature_Extern
39+
// REQUIRES: swift_feature_LifetimeDependence
3740
// REQUIRES: swift_feature_NonIsolatedAsyncInheritsIsolationFromContext
41+
// REQUIRES: swift_feature_SymbolLinkageMarkers
3842

3943
// rdar://116686158
4044
// UNSUPPORTED: asan
@@ -201,3 +205,13 @@ struct OpTest {
201205
func opResult() -> some OpProto { OpStruct() }
202206
typealias Result = @_opaqueReturnTypeOf("$s6ASTGen6OpTestV8opResultQryF", 0) __
203207
}
208+
209+
struct E {}
210+
struct NE : ~Escapable {}
211+
@lifetime(ne) func derive(_ ne: NE) -> NE { ne }
212+
@lifetime(borrow ne1, ne2) func derive(_ ne1: NE, _ ne2: NE) -> NE {
213+
if (Int.random(in: 1..<100) < 50) { return ne1 }
214+
return ne2
215+
}
216+
@lifetime(borrow borrow) func testNameConflict(_ borrow: E) -> NE { NE() }
217+
@lifetime(result: source) func testTarget(_ result: inout NE, _ source: consuming NE) { result = source }

0 commit comments

Comments
 (0)