termux-packages/packages/swift/swift-modify-astgen.patch

741 lines
28 KiB
Diff

From dba94bdbd4f4b1e9b3b271409cbc5d1bb49ddaf3
From: Doug Gregor <dgregor@apple.com>
Date: Fri, 19 May 2023 15:02:42 -0700
Subject: [PATCH] [ASTGen] Add experimental feature to use ASTGen in lieu
of parsing types
Introduce a new experimental feature `ASTGenTypes` that uses ASTGen to
translate the Swift syntax tree (produced by the new Swift parser)
into C++ `TypeRepr` nodes instead of having the C++ parser create the
nodes.
The approach here is to intercept the C++ parser's `parseType`
operation to find the Swift syntax node at the given position (where
the lexer currently is) and have ASTGen translate that into the
corresponding C++ AST node. Then, we spin the lexer forward to the
token immediately following the end of the syntax node and continue
parsing.
diff --git a/swift/include/swift/AST/CASTBridging.h b/swift/include/swift/AST/CASTBridging.h
index 4699a291a1f..dd24e573561 100644
--- a/swift/include/swift/AST/CASTBridging.h
+++ b/swift/include/swift/AST/CASTBridging.h
@@ -112,6 +112,70 @@ typedef enum ENUM_EXTENSIBILITY_ATTR(open) BridgedMacroDefinitionKind : long {
BridgedBuiltinExternalMacro
} BridgedMacroDefinitionKind;
+/// Bridged parameter specifiers
+typedef enum ENUM_EXTENSIBILITY_ATTR(open) BridgedAttributedTypeSpecifier : long {
+ BridgedAttributedTypeSpecifierInOut,
+ BridgedAttributedTypeSpecifierBorrowing,
+ BridgedAttributedTypeSpecifierConsuming,
+ BridgedAttributedTypeSpecifierLegacyShared,
+ BridgedAttributedTypeSpecifierLegacyOwned,
+ BridgedAttributedTypeSpecifierConst,
+ BridgedAttributedTypeSpecifierIsolated,
+} BridgedAttributedTypeSpecifier;
+
+
+// Bridged type attribute kinds, which mirror TypeAttrKind exactly.
+typedef enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedTypeAttrKind : long {
+ BridgedTypeAttrKind_autoclosure,
+ BridgedTypeAttrKind_convention,
+ BridgedTypeAttrKind_noescape,
+ BridgedTypeAttrKind_escaping,
+ BridgedTypeAttrKind_differentiable,
+ BridgedTypeAttrKind_noDerivative,
+ BridgedTypeAttrKind_async,
+ BridgedTypeAttrKind_Sendable,
+ BridgedTypeAttrKind_unchecked,
+ BridgedTypeAttrKind__local,
+ BridgedTypeAttrKind__noMetadata,
+ BridgedTypeAttrKind__opaqueReturnTypeOf,
+ BridgedTypeAttrKind_block_storage,
+ BridgedTypeAttrKind_box,
+ BridgedTypeAttrKind_dynamic_self,
+ BridgedTypeAttrKind_sil_weak,
+ BridgedTypeAttrKind_sil_unowned,
+ BridgedTypeAttrKind_sil_unmanaged,
+ BridgedTypeAttrKind_error,
+ BridgedTypeAttrKind_out,
+ BridgedTypeAttrKind_direct,
+ BridgedTypeAttrKind_in,
+ BridgedTypeAttrKind_inout,
+ BridgedTypeAttrKind_inout_aliasable,
+ BridgedTypeAttrKind_in_guaranteed,
+ BridgedTypeAttrKind_in_constant,
+ BridgedTypeAttrKind_pack_owned,
+ BridgedTypeAttrKind_pack_guaranteed,
+ BridgedTypeAttrKind_pack_inout,
+ BridgedTypeAttrKind_pack_out,
+ BridgedTypeAttrKind_owned,
+ BridgedTypeAttrKind_unowned_inner_pointer,
+ BridgedTypeAttrKind_guaranteed,
+ BridgedTypeAttrKind_autoreleased,
+ BridgedTypeAttrKind_callee_owned,
+ BridgedTypeAttrKind_callee_guaranteed,
+ BridgedTypeAttrKind_objc_metatype,
+ BridgedTypeAttrKind_opened,
+ BridgedTypeAttrKind_pack_element,
+ BridgedTypeAttrKind_pseudogeneric,
+ BridgedTypeAttrKind_yields,
+ BridgedTypeAttrKind_yield_once,
+ BridgedTypeAttrKind_yield_many,
+ BridgedTypeAttrKind_captures_generics,
+ BridgedTypeAttrKind_moveOnly,
+ BridgedTypeAttrKind_thin,
+ BridgedTypeAttrKind_thick,
+ BridgedTypeAttrKind_Count
+} BridgedTypeAttrKind;
+
#ifdef __cplusplus
extern "C" {
@@ -261,6 +325,19 @@ void *ImplicitlyUnwrappedOptionalTypeRepr_create(void *ctx, void *base,
void *exclamationLoc);
void *MetatypeTypeRepr_create(void *ctx, void *baseType, void *typeLoc);
void *ProtocolTypeRepr_create(void *ctx, void *baseType, void *protoLoc);
+
+BridgedTypeAttrKind getBridgedTypeAttrKindFromString(
+ const unsigned char * _Nullable str, long len);
+
+typedef void *BridgedTypeAttributes;
+BridgedTypeAttributes BridgedTypeAttributes_create(void);
+void BridgedTypeAttributes_addSimpleAttr(
+ BridgedTypeAttributes typeAttributes, BridgedTypeAttrKind kind, void *atLoc, void *attrLoc);
+void *AttributedTypeRepr_create(void *ctx, void *base, BridgedTypeAttributes typeAttributes);
+
+void *AttributedTypeSpecifierRepr_create(
+ void *ctx, void *base, BridgedAttributedTypeSpecifier specifier, void *specifierLoc);
+void *VarargTypeRepr_create(void *ctx, void *base, void *ellipsisLocPtr);
void *PackExpansionTypeRepr_create(void *ctx, void *base, void *repeatLoc);
void *TupleTypeRepr_create(void *ctx, BridgedArrayRef elements, void *lParenLoc,
void *rParenLoc);
@@ -269,8 +346,9 @@ void *MemberTypeRepr_create(void *ctx, void *baseComponent,
void *GenericIdentTypeRepr_create(void *ctx, BridgedIdentifier name,
void *nameLoc, BridgedArrayRef genericArgs,
void *lAngle, void *rAngle);
+void *EmptyCompositionTypeRepr_create(void *ctx, void *anyLoc);
void *CompositionTypeRepr_create(void *ctx, BridgedArrayRef types,
- void *firstTypeLoc);
+ void *firstTypeLoc, void *firstAmpLoc);
void *FunctionTypeRepr_create(void *ctx, void *argsTy, void *_Nullable asyncLoc,
void *_Nullable throwsLoc, void *arrowLoc,
void *returnType);
diff --git a/swift/include/swift/Basic/Features.def b/swift/include/swift/Basic/Features.def
index d3b6ed2519f..d0884deafe4 100644
--- a/swift/include/swift/Basic/Features.def
+++ b/swift/include/swift/Basic/Features.def
@@ -184,6 +184,10 @@ EXPERIMENTAL_FEATURE(ImplicitSome, false)
/// corresponding syntax tree.
EXPERIMENTAL_FEATURE(ParserASTGen, false)
+/// Use the syntax tree produced by the Swift (swift-syntax) parser for type
+/// parsing, using ASTGen to translate them into AST nodes.
+EXPERIMENTAL_FEATURE(ASTGenTypes, false)
+
/// Parse using the Swift (swift-syntax) parser and use ASTGen to generate the
/// corresponding syntax tree.
EXPERIMENTAL_FEATURE(BuiltinMacros, false)
diff --git a/swift/include/swift/Parse/Parser.h b/swift/include/swift/Parse/Parser.h
index a1ac3666776..2ba8c645833 100644
--- a/swift/include/swift/Parse/Parser.h
+++ b/swift/include/swift/Parse/Parser.h
@@ -24,6 +24,7 @@
#include "swift/AST/LayoutConstraint.h"
#include "swift/AST/ParseRequests.h"
#include "swift/AST/Pattern.h"
+#include "swift/AST/SourceFile.h"
#include "swift/AST/Stmt.h"
#include "swift/Basic/OptionSet.h"
#include "swift/Config.h"
@@ -1343,6 +1344,50 @@ public:
/// Get the location for a type error.
SourceLoc getTypeErrorLoc() const;
+ /// Callback function used for creating a C++ AST from the syntax node at the given source location.
+ ///
+ /// The arguments to this callback are the source file to pass into ASTGen (the exported source file)
+ /// and the source location pointer to pass into ASTGen (to find the syntax node).
+ ///
+ /// The callback returns the new AST node and the ending location of the syntax node. If the AST node
+ /// is NULL, something went wrong.
+ template<typename T>
+ using ASTFromSyntaxTreeCallback = std::pair<T*, const void *>(
+ void *sourceFile, const void *sourceLoc
+ );
+
+ /// Parse by constructing a C++ AST node from the Swift syntax tree via ASTGen.
+ template<typename T>
+ ParserResult<T> parseASTFromSyntaxTree(
+ llvm::function_ref<ASTFromSyntaxTreeCallback<T>> body
+ ) {
+ if (!Context.LangOpts.hasFeature(Feature::ASTGenTypes))
+ return nullptr;
+
+ auto exportedSourceFile = SF.getExportedSourceFile();
+ if (!exportedSourceFile)
+ return nullptr;
+
+ // Perform the translation.
+ auto sourceLoc = Tok.getLoc().getOpaquePointerValue();
+ T* astNode;
+ const void *endLocPtr;
+ std::tie(astNode, endLocPtr) = body(exportedSourceFile, sourceLoc);
+
+ if (!astNode) {
+ assert(false && "Could not build AST node from syntax tree");
+ return nullptr;
+ }
+
+ // Reset the lexer to the ending location.
+ StringRef contents =
+ SourceMgr.extractText(SourceMgr.getRangeForBuffer(L->getBufferID()));
+ L->resetToOffset((const char *)endLocPtr - contents.data());
+ L->lex(Tok);
+
+ return makeParserResult(astNode);
+ }
+
//===--------------------------------------------------------------------===//
// Type Parsing
diff --git a/swift/lib/AST/ASTPrinter.cpp b/swift/lib/AST/ASTPrinter.cpp
index 7f24711916c..474e62aa8dc 100644
--- a/swift/lib/AST/ASTPrinter.cpp
+++ b/swift/lib/AST/ASTPrinter.cpp
@@ -3364,6 +3364,10 @@ static bool usesFeatureParserASTGen(Decl *decl) {
return false;
}
+static bool usesFeatureASTGenTypes(Decl *decl) {
+ return false;
+}
+
static bool usesFeatureBuiltinMacros(Decl *decl) {
return false;
}
diff --git a/swift/lib/AST/CASTBridging.cpp b/swift/lib/AST/CASTBridging.cpp
index 5b935d4cebb..2f7c14fd1a2 100644
--- a/swift/lib/AST/CASTBridging.cpp
+++ b/swift/lib/AST/CASTBridging.cpp
@@ -119,6 +119,15 @@ void SwiftDiagnostic_finish(BridgedDiagnostic diagPtr) {
BridgedIdentifier
SwiftASTContext_getIdentifier(void *ctx, const unsigned char *_Nullable str,
long len) {
+ if (len == 1 && str[0] == '_')
+ return BridgedIdentifier();
+
+ // If this was a back-ticked identifier, drop the back-ticks.
+ if (len >= 2 && str[0] == '`' && str[len-1] == '`') {
+ ++str;
+ len -= 2;
+ }
+
return const_cast<void *>(
static_cast<ASTContext *>(ctx)
->getIdentifier(
@@ -484,6 +493,87 @@ void *PackExpansionTypeRepr_create(void *ctx, void *base, void *repeatLoc) {
getSourceLocFromPointer(repeatLoc), (TypeRepr *)base);
}
+static BridgedTypeAttrKind bridgeTypeAttrKind(TypeAttrKind kind) {
+ switch (kind) {
+#define TYPE_ATTR(X) case TAK_##X: return BridgedTypeAttrKind_##X;
+#include "swift/AST/Attr.def"
+ case TAK_Count: return BridgedTypeAttrKind_Count;
+ }
+}
+
+static TypeAttrKind bridgeTypeAttrKind(BridgedTypeAttrKind kind) {
+ switch (kind) {
+#define TYPE_ATTR(X) case BridgedTypeAttrKind_##X: return TAK_##X;
+#include "swift/AST/Attr.def"
+ case BridgedTypeAttrKind_Count: return TAK_Count;
+ }
+}
+
+BridgedTypeAttrKind getBridgedTypeAttrKindFromString(
+ const unsigned char *str, intptr_t len) {
+ return bridgeTypeAttrKind(
+ TypeAttributes::getAttrKindFromString(StringRef((const char *)str, len)));
+}
+
+BridgedTypeAttributes BridgedTypeAttributes_create() {
+ return new TypeAttributes();
+}
+
+void BridgedTypeAttributes_addSimpleAttr(
+ BridgedTypeAttributes typeAttributesPtr, BridgedTypeAttrKind kind,
+ void *atLoc, void *attrLoc
+) {
+ TypeAttributes *typeAttributes = (TypeAttributes *)typeAttributesPtr;
+ typeAttributes->setAttr(
+ bridgeTypeAttrKind(kind), getSourceLocFromPointer(attrLoc));
+ if (typeAttributes->AtLoc.isInvalid())
+ typeAttributes->AtLoc = getSourceLocFromPointer(atLoc);
+}
+
+void *AttributedTypeRepr_create(
+ void *ctx, void *base, BridgedTypeAttributes typeAttributesPtr) {
+ TypeAttributes *typeAttributes = (TypeAttributes *)typeAttributesPtr;
+ if (typeAttributes->empty())
+ return base;
+
+ ASTContext &Context = *static_cast<ASTContext *>(ctx);
+ auto attributedType =
+ new (Context) AttributedTypeRepr(*typeAttributes, (TypeRepr *)base);
+ delete typeAttributes;
+ return attributedType;
+}
+
+void *AttributedTypeSpecifierRepr_create(
+ void *ctx, void *base, BridgedAttributedTypeSpecifier specifier, void *specifierLoc
+) {
+ ASTContext &Context = *static_cast<ASTContext *>(ctx);
+ SourceLoc loc = getSourceLocFromPointer(specifierLoc);
+ TypeRepr *baseType = (TypeRepr *)base;
+ switch (specifier) {
+ case BridgedAttributedTypeSpecifierInOut:
+ return new (Context) OwnershipTypeRepr(baseType, ParamSpecifier::InOut, loc);
+ case BridgedAttributedTypeSpecifierBorrowing:
+ return new (Context) OwnershipTypeRepr(baseType, ParamSpecifier::Borrowing, loc);
+ case BridgedAttributedTypeSpecifierConsuming:
+ return new (Context) OwnershipTypeRepr(baseType, ParamSpecifier::Consuming, loc);
+ case BridgedAttributedTypeSpecifierLegacyShared:
+ return new (Context) OwnershipTypeRepr(baseType, ParamSpecifier::LegacyShared, loc);
+ case BridgedAttributedTypeSpecifierLegacyOwned:
+ return new (Context) OwnershipTypeRepr(baseType, ParamSpecifier::LegacyOwned, loc);
+ case BridgedAttributedTypeSpecifierConst:
+ return new (Context) CompileTimeConstTypeRepr(baseType, loc);
+ case BridgedAttributedTypeSpecifierIsolated:
+ return new (Context) IsolatedTypeRepr(baseType, loc);
+ }
+}
+
+void *VarargTypeRepr_create(void *ctx, void *base, void *ellipsisLocPtr) {
+ ASTContext &Context = *static_cast<ASTContext *>(ctx);
+ SourceLoc ellipsisLoc = getSourceLocFromPointer(ellipsisLocPtr);
+ TypeRepr *baseType = (TypeRepr *)base;
+ return new (Context) VarargTypeRepr(baseType, ellipsisLoc);
+}
+
void *TupleTypeRepr_create(void *ctx, BridgedArrayRef elements, void *lParenLoc,
void *rParenLoc) {
ASTContext &Context = *static_cast<ASTContext *>(ctx);
@@ -518,12 +608,21 @@ void *MemberTypeRepr_create(void *ctx, void *baseComponent,
memberComponents);
}
-void *CompositionTypeRepr_create(void *ctx, BridgedArrayRef types,
- void *firstTypeLoc) {
+void *EmptyCompositionTypeRepr_create(void *ctx, void *anyLocPtr) {
+ ASTContext &Context = *static_cast<ASTContext *>(ctx);
+ SourceLoc anyLoc = getSourceLocFromPointer(anyLocPtr);
+ return CompositionTypeRepr::createEmptyComposition(Context, anyLoc);
+}
+
+void *CompositionTypeRepr_create(void *ctx, BridgedArrayRef typesPtr,
+ void *firstTypeLoc, void *firstAmpLocPtr) {
ASTContext &Context = *static_cast<ASTContext *>(ctx);
SourceLoc firstType = getSourceLocFromPointer(firstTypeLoc);
- return CompositionTypeRepr::create(Context, getArrayRef<TypeRepr *>(types),
- firstType, SourceRange{});
+ SourceLoc firstAmpLoc = getSourceLocFromPointer(firstAmpLocPtr);
+ auto types = getArrayRef<TypeRepr *>(typesPtr);
+ return CompositionTypeRepr::create(
+ Context, types, firstType,
+ SourceRange{firstAmpLoc, types.back()->getEndLoc()});
}
void *FunctionTypeRepr_create(void *ctx, void *argsTy, void *_Nullable asyncLoc,
diff --git a/swift/lib/ASTGen/Sources/ASTGen/Macros.swift b/swift/lib/ASTGen/Sources/ASTGen/Macros.swift
index 4ee025884bd..81e355f475d 100644
--- a/swift/lib/ASTGen/Sources/ASTGen/Macros.swift
+++ b/swift/lib/ASTGen/Sources/ASTGen/Macros.swift
@@ -627,10 +627,11 @@ func expandFreestandingMacroInProcess(
}
/// Retrieve a syntax node in the given source file, with the given type.
-private func findSyntaxNodeInSourceFile<Node: SyntaxProtocol>(
+func findSyntaxNodeInSourceFile<Node: SyntaxProtocol>(
sourceFilePtr: UnsafeRawPointer,
sourceLocationPtr: UnsafePointer<UInt8>?,
- type: Node.Type
+ type: Node.Type,
+ wantOutermost: Bool = false
) -> Node? {
guard let sourceLocationPtr = sourceLocationPtr else {
return nil
@@ -656,16 +657,45 @@ private func findSyntaxNodeInSourceFile<Node: SyntaxProtocol>(
}
var currentSyntax = Syntax(token)
+ var resultSyntax: Node? = nil
while let parentSyntax = currentSyntax.parent {
if let typedParent = parentSyntax.as(type) {
- return typedParent
+ resultSyntax = typedParent
+ break
}
currentSyntax = parentSyntax
}
- print("unable to find node: \(token.debugDescription)")
- return nil
+ // If we didn't find anything, complain and fail.
+ guard var resultSyntax else {
+ print("unable to find node: \(token.debugDescription)")
+ return nil
+ }
+
+ // If we want the outermost node, keep looking.
+ // FIXME: This is VERY SPECIFIC to handling of types. We must be able to
+ // do better.
+ if wantOutermost {
+ while let parentSyntax = resultSyntax.parent {
+ // Look through type compositions.
+ if let compositionElement = parentSyntax.as(CompositionTypeElementSyntax.self),
+ let compositionList = compositionElement.parent?.as(CompositionTypeElementListSyntax.self),
+ let typedParent = compositionList.parent?.as(type) {
+ resultSyntax = typedParent
+ continue
+ }
+
+ guard let typedParent = parentSyntax.as(type),
+ typedParent.position == resultSyntax.position else {
+ break
+ }
+
+ resultSyntax = typedParent
+ }
+ }
+
+ return resultSyntax
}
@_cdecl("swift_ASTGen_expandAttachedMacro")
diff --git a/swift/lib/ASTGen/Sources/ASTGen/Types.swift b/swift/lib/ASTGen/Sources/ASTGen/Types.swift
index eb2be48a8a8..82bbca53bf4 100644
--- a/swift/lib/ASTGen/Sources/ASTGen/Types.swift
+++ b/swift/lib/ASTGen/Sources/ASTGen/Types.swift
@@ -6,6 +6,11 @@ extension ASTGenVisitor {
public func visit(_ node: SimpleTypeIdentifierSyntax) -> ASTNode {
let loc = self.base.advanced(by: node.position.utf8Offset).raw
+ // If this is the bare 'Any' keyword, produce an empty composition type.
+ if node.name.tokenKind == .keyword(.Any) && node.genericArgumentClause == nil {
+ return .type(EmptyCompositionTypeRepr_create(self.ctx, loc))
+ }
+
var text = node.name.text
let id = text.withUTF8 { buf in
return SwiftASTContext_getIdentifier(ctx, buf.baseAddress, buf.count)
@@ -19,7 +24,7 @@ extension ASTGenVisitor {
let rAngle = self.base.advanced(by: generics.rightAngleBracket.position.utf8Offset).raw
return .type(
generics.arguments.map({
- self.visit($0.argumentType)
+ self.visit($0.argumentType).rawValue
}).withBridgedArrayRef {
genericArgs in
GenericIdentTypeRepr_create(
@@ -46,7 +51,7 @@ extension ASTGenVisitor {
let lAngle = self.base.advanced(by: generics.leftAngleBracket.position.utf8Offset).raw
let rAngle = self.base.advanced(by: generics.rightAngleBracket.position.utf8Offset).raw
reverseMemberComponents.append(
- generics.arguments.map({ self.visit($0.argumentType) }).withBridgedArrayRef {
+ generics.arguments.map({ self.visit($0.argumentType).rawValue }).withBridgedArrayRef {
genericArgs in
GenericIdentTypeRepr_create(self.ctx, name, nameLoc, genericArgs, lAngle, rAngle)
})
@@ -123,9 +128,11 @@ extension ASTGenVisitor {
assert(node.elements.count > 1)
let types = node.elements.map { visit($0.type) }.map { $0.rawValue }
let firstTypeLoc = self.base.advanced(by: node.elements.first!.type.position.utf8Offset).raw
+ let firstAmpOffset = node.elements.first?.ampersand.map { $0.position.utf8Offset } ?? 0
+ let firstAmpLoc = self.base.advanced(by: firstAmpOffset).raw
return .type(
types.withBridgedArrayRef { types in
- return CompositionTypeRepr_create(self.ctx, types, firstTypeLoc)
+ return CompositionTypeRepr_create(self.ctx, types, firstTypeLoc, firstAmpLoc)
})
}
@@ -161,8 +168,77 @@ extension ASTGenVisitor {
}
public func visit(_ node: AttributedTypeSyntax) -> ASTNode {
- // FIXME: Respect the attributes
- return visit(node.baseType)
+ var type = visit(node.baseType)
+
+ // Handle specifiers.
+ if let specifier = node.specifier {
+ let specifierLoc = self.base.advanced(by: specifier.position.utf8Offset).raw
+
+ let kind: BridgedAttributedTypeSpecifier
+ switch specifier.tokenKind {
+ case .keyword(.inout): kind = .inOut
+ case .keyword(.borrowing): kind = .borrowing
+ case .keyword(.consuming): kind = .consuming
+ case .keyword(.__shared): kind = .legacyShared
+ case .keyword(.__owned): kind = .legacyOwned
+ case .keyword(._const): kind = .const
+ case .keyword(.isolated): kind = .isolated
+ default: fatalError("unhandled specifier \(specifier.debugDescription)")
+ }
+
+ type = .type(AttributedTypeSpecifierRepr_create(self.ctx, type.rawValue, kind, specifierLoc))
+ }
+
+ // Handle type attributes.
+ if let attributes = node.attributes {
+ let typeAttributes = BridgedTypeAttributes_create()
+ for attributeElt in attributes {
+ // FIXME: Ignoring #ifs entirely. We want to provide a filtered view,
+ // but we don't have that ability right now.
+ guard case let .attribute(attribute) = attributeElt else {
+ continue
+ }
+
+ // Only handle simple attribute names right now.
+ guard let identType = attribute.attributeName.as(SimpleTypeIdentifierSyntax.self) else {
+ continue
+ }
+
+ let nameSyntax = identType.name
+ var name = nameSyntax.text
+ let typeAttrKind = name.withUTF8 { buf in
+ getBridgedTypeAttrKindFromString(buf.baseAddress, buf.count)
+ }
+ let atLoc = self.base.advanced(by: attribute.atSignToken.position.utf8Offset).raw
+ let attrLoc = self.base.advanced(by: nameSyntax.position.utf8Offset).raw
+ switch typeAttrKind {
+ // SIL attributes
+ // FIXME: Diagnose if not in SIL mode? Or should that move to the
+ // type checker?
+ case .out, .in, .owned, .unowned_inner_pointer, .guaranteed,
+ .autoreleased, .callee_owned, .callee_guaranteed, .objc_metatype,
+ .sil_weak, .sil_unowned, .inout, .block_storage, .box,
+ .dynamic_self, .sil_unmanaged, .error, .direct, .inout_aliasable,
+ .in_guaranteed, .in_constant, .captures_generics, .moveOnly:
+ fallthrough
+
+ case .autoclosure, .escaping, .noescape, .noDerivative, .async,
+ .sendable, .unchecked, ._local, ._noMetadata, .pack_owned,
+ .pack_guaranteed, .pack_inout, .pack_out, .pseudogeneric,
+ .yields, .yield_once, .yield_many, .thin, .thick, .count:
+ BridgedTypeAttributes_addSimpleAttr(typeAttributes, typeAttrKind, atLoc, attrLoc)
+
+ case .opened, .pack_element, .differentiable, .convention,
+ ._opaqueReturnTypeOf:
+ // FIXME: These require more complicated checks
+ break
+ }
+ }
+
+ type = .type(AttributedTypeRepr_create(self.ctx, type.rawValue, typeAttributes))
+ }
+
+ return type
}
}
@@ -186,7 +262,13 @@ extension ASTGenVisitor {
self.base.advanced(by: $0.position.utf8Offset).raw
}
let colonLoc = element.colon.map { self.base.advanced(by: $0.position.utf8Offset).raw }
- let type = visit(element.type).rawValue
+
+ var type = visit(element.type).rawValue
+ if let ellipsis = element.ellipsis {
+ let ellipsisLoc = self.base.advanced(by: ellipsis.positionAfterSkippingLeadingTrivia.utf8Offset).raw
+ type = VarargTypeRepr_create(self.ctx, type, ellipsisLoc)
+ }
+
let trailingCommaLoc = element.trailingComma.map {
self.base.advanced(by: $0.position.utf8Offset).raw
}
@@ -207,3 +289,37 @@ extension ASTGenVisitor {
}
}
}
+
+@_cdecl("swift_ASTGen_buildTypeRepr")
+@usableFromInline
+func buildTypeRepr(
+ sourceFilePtr: UnsafeRawPointer,
+ typeLocPtr: UnsafePointer<UInt8>,
+ dc: UnsafeMutableRawPointer,
+ ctx: UnsafeMutableRawPointer,
+ endTypeLocPtr: UnsafeMutablePointer<UnsafePointer<UInt8>?>
+) -> UnsafeMutableRawPointer? {
+ let sourceFile = sourceFilePtr.bindMemory(
+ to: ExportedSourceFile.self, capacity: 1
+ )
+
+ // Find the type syntax node.
+ guard let typeSyntax = findSyntaxNodeInSourceFile(
+ sourceFilePtr: sourceFilePtr,
+ sourceLocationPtr: typeLocPtr,
+ type: TypeSyntax.self,
+ wantOutermost: true
+ ) else {
+ // FIXME: Produce an error
+ return nil
+ }
+
+ // Fill in the end location.
+ endTypeLocPtr.pointee = sourceFile.pointee.buffer.baseAddress!.advanced(by: typeSyntax.endPosition.utf8Offset)
+
+ // Convert the type syntax node.
+ let typeReprNode = ASTGenVisitor(ctx: ctx, base: sourceFile.pointee.buffer.baseAddress!, declContext: dc)
+ .visit(typeSyntax)
+
+ return typeReprNode.rawValue
+}
diff --git a/swift/lib/Parse/ParseType.cpp b/swift/lib/Parse/ParseType.cpp
index 98a1cb0a4fc..97c88da9bbd 100644
--- a/swift/lib/Parse/ParseType.cpp
+++ b/swift/lib/Parse/ParseType.cpp
@@ -582,6 +582,14 @@ ParserResult<TypeRepr> Parser::parseTypeScalar(
constLoc));
}
+/// Build a TypeRepr for AST node for the type at the given source location in the specified file.
+///
+/// \param sourceLoc The source location at which to start processing a type.
+/// \param endSourceLoc Will receive the source location immediately following the type.
+extern "C" TypeRepr *swift_ASTGen_buildTypeRepr(
+ void *sourceFile, const void *_Nullable sourceLoc,
+ void *declContext, void *astContext, const void *_Nullable *endSourceLoc);
+
/// parseType
/// type:
/// type-scalar
@@ -592,6 +600,32 @@ ParserResult<TypeRepr> Parser::parseTypeScalar(
///
ParserResult<TypeRepr> Parser::parseType(
Diag<> MessageID, ParseTypeReason reason) {
+ #if SWIFT_SWIFT_PARSER
+ auto astGenResult = parseASTFromSyntaxTree<TypeRepr>(
+ [&](void *exportedSourceFile, const void *sourceLoc) {
+ const void *endLocPtr = nullptr;
+ TypeRepr *typeRepr = swift_ASTGen_buildTypeRepr(
+ exportedSourceFile, Tok.getLoc().getOpaquePointerValue(),
+ CurDeclContext, &Context, &endLocPtr);
+ return std::make_pair(typeRepr, endLocPtr);
+ });
+ if (astGenResult.isNonNull()) {
+ // Note: there is a representational difference between the swift-syntax
+ // tree and the C++ parser tree regarding variadic parameters. In the
+ // swift-syntax tree, the ellipsis is part of the parameter declaration.
+ // In the C++ parser tree, the ellipsis is part of the type. Account for
+ // this difference by consuming the ellipsis here.
+ if (Tok.isEllipsis()) {
+ Tok.setKind(tok::ellipsis);
+ SourceLoc ellipsisLoc = consumeToken();
+ return makeParserResult(astGenResult,
+ new (Context) VarargTypeRepr(astGenResult.get(), ellipsisLoc));
+ }
+
+ return astGenResult;
+ }
+ #endif
+
// Parse pack expansion 'repeat T'
if (Tok.is(tok::kw_repeat)) {
SourceLoc repeatLoc = consumeToken(tok::kw_repeat);
diff --git a/swift/test/ASTGen/types.swift b/swift/test/ASTGen/types.swift
new file mode 100644
index 00000000000..f6eddfe1ed6
--- /dev/null
+++ b/swift/test/ASTGen/types.swift
@@ -0,0 +1,41 @@
+// RUN: %target-typecheck-verify-swift -enable-experimental-feature ASTGenTypes
+
+// -enable-experimental-feature requires an asserts build
+// REQUIRES: asserts
+
+protocol P { }
+protocol Q { }
+typealias PQ = P & Q
+
+func test7(_ b: inout Bool) {
+ b = true
+}
+
+struct X { struct `Protocol` { } }
+
+func test10(_: X.`Protocol`) { }
+
+func test11(_: Int...) { }
+func test11a() {
+ test11(1, 2, 3, 4, 5)
+}
+
+typealias VAFunc = (Int, Int...) -> Int
+func testVAFunc(a: Int, f: VAFunc) {
+ _ = f(a, a, a, a, a)
+}
+
+func test12(_ producer: @escaping @autoclosure () -> Int) {
+ _ = producer()
+}
+func test12a(i: Int) {
+ test12(i)
+}
+
+func test13(body: (_ value: Int) -> Void, i: Int) {
+ body(i)
+}
+
+func test14() {
+ _ = Array<Array<Array<Int>>>().count
+}
diff --git a/swift/test/ASTGen/verify-parse.swift b/swift/test/ASTGen/verify-parse.swift
index ec5004eb129..9bdc36cb4f0 100644
--- a/swift/test/ASTGen/verify-parse.swift
+++ b/swift/test/ASTGen/verify-parse.swift
@@ -1,8 +1,9 @@
// RUN: %target-run-simple-swift(-enable-experimental-feature SwiftParser -enable-experimental-feature ParserASTGen)
+// RUN: %target-run-simple-swift(-enable-experimental-feature ASTGenTypes)
// REQUIRES: executable_test
-// -enable-experimental-feature requires and asserts build
+// -enable-experimental-feature requires an asserts build
// REQUIRES: asserts
func test1(x: Int, fn: (Int) -> Int) -> Int {
@@ -25,11 +26,11 @@ func test3(y: Int) -> Int {
return x
}
-func test4(_ b: Bool) -> Int {
- if b { 0 } else { 1 }
+func test4(_ b: [Bool]) -> Int {
+ if b.isEmpty { 0 } else { 1 }
}
-func test5(_ b: Bool) -> Int {
+func test5(_ b: Swift.Bool) -> Int {
return if b { 0 } else { 1 }
}
@@ -37,3 +38,12 @@ func test6(_ b: Bool) -> Int {
let x = if b { 0 } else { 1 }
return x
}
+
+func test7(_ b: inout Bool) {
+ // b = true
+}
+
+func test8(_ i: _const Int) {
+}
+
+func test9(_ value: Any) { }