diff --git a/include/swift/AST/CASTBridging.h b/include/swift/AST/CASTBridging.h index 16ae10732fce2..9647ddf561f14 100644 --- a/include/swift/AST/CASTBridging.h +++ b/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/include/swift/Basic/Features.def b/include/swift/Basic/Features.def index 500b7648c6e53..c9695c4c0557f 100644 --- a/include/swift/Basic/Features.def +++ b/include/swift/Basic/Features.def @@ -174,6 +174,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/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index fbe291cd18f5f..347f967418bf7 100644 --- a/include/swift/Parse/Parser.h +++ b/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" @@ -1330,6 +1331,50 @@ class Parser { /// 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 + using ASTFromSyntaxTreeCallback = std::pair( + void *sourceFile, const void *sourceLoc + ); + + /// Parse by constructing a C++ AST node from the Swift syntax tree via ASTGen. + template + ParserResult parseASTFromSyntaxTree( + llvm::function_ref> 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/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 00cb4a6d492d8..4910011645b4a 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -3321,6 +3321,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/lib/AST/CASTBridging.cpp b/lib/AST/CASTBridging.cpp index b7f4e4305cb11..b76dcfa8e5cc8 100644 --- a/lib/AST/CASTBridging.cpp +++ b/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( static_cast(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(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(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(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(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(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(ctx); SourceLoc firstType = getSourceLocFromPointer(firstTypeLoc); - return CompositionTypeRepr::create(Context, getArrayRef(types), - firstType, SourceRange{}); + SourceLoc firstAmpLoc = getSourceLocFromPointer(firstAmpLocPtr); + auto types = getArrayRef(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/lib/ASTGen/Sources/ASTGen/Macros.swift b/lib/ASTGen/Sources/ASTGen/Macros.swift index 12fbaaf20c420..f4eeb3bb30d11 100644 --- a/lib/ASTGen/Sources/ASTGen/Macros.swift +++ b/lib/ASTGen/Sources/ASTGen/Macros.swift @@ -586,10 +586,11 @@ func expandFreestandingMacroInProcess( } /// Retrieve a syntax node in the given source file, with the given type. -private func findSyntaxNodeInSourceFile( +func findSyntaxNodeInSourceFile( sourceFilePtr: UnsafeRawPointer, sourceLocationPtr: UnsafePointer?, - type: Node.Type + type: Node.Type, + wantOutermost: Bool = false ) -> Node? { guard let sourceLocationPtr = sourceLocationPtr else { return nil @@ -615,16 +616,45 @@ private func findSyntaxNodeInSourceFile( } 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/lib/ASTGen/Sources/ASTGen/Types.swift b/lib/ASTGen/Sources/ASTGen/Types.swift index eb2be48a8a89b..82bbca53bf4b2 100644 --- a/lib/ASTGen/Sources/ASTGen/Types.swift +++ b/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, + dc: UnsafeMutableRawPointer, + ctx: UnsafeMutableRawPointer, + endTypeLocPtr: UnsafeMutablePointer?> +) -> 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/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp index 2221d0610754d..d1d1708ec96e8 100644 --- a/lib/Parse/ParseType.cpp +++ b/lib/Parse/ParseType.cpp @@ -572,6 +572,14 @@ ParserResult 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 @@ -582,6 +590,32 @@ ParserResult Parser::parseTypeScalar( /// ParserResult Parser::parseType( Diag<> MessageID, ParseTypeReason reason) { + #if SWIFT_SWIFT_PARSER + auto astGenResult = parseASTFromSyntaxTree( + [&](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/test/ASTGen/types.swift b/test/ASTGen/types.swift new file mode 100644 index 0000000000000..f6eddfe1ed62e --- /dev/null +++ b/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>>().count +} diff --git a/test/ASTGen/verify-parse.swift b/test/ASTGen/verify-parse.swift index ec5004eb12972..9bdc36cb4f094 100644 --- a/test/ASTGen/verify-parse.swift +++ b/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) { }