From ba3bc1d5f11c7c62fe3dd46cc2e9e68aab75c1d1 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Thu, 17 Oct 2024 13:09:17 -0700 Subject: [PATCH 01/10] Implement ASTGen changes for integer generics from Swift Syntax Support negatives --- include/swift/AST/ASTBridging.h | 6 + lib/AST/Bridging/TypeReprBridging.cpp | 10 ++ lib/ASTGen/Sources/ASTGen/Exprs.swift | 2 +- lib/ASTGen/Sources/ASTGen/Generics.swift | 119 +++++++++++++++++- lib/ASTGen/Sources/ASTGen/Types.swift | 4 +- .../DistributedResolvableMacro.swift | 20 ++- .../Sources/SwiftMacros/OptionSetMacro.swift | 2 +- 7 files changed, 153 insertions(+), 10 deletions(-) diff --git a/include/swift/AST/ASTBridging.h b/include/swift/AST/ASTBridging.h index 9a9e8544c1719..0e52d8156fc46 100644 --- a/include/swift/AST/ASTBridging.h +++ b/include/swift/AST/ASTBridging.h @@ -1938,6 +1938,12 @@ BridgedVarargTypeRepr_createParsed(BridgedASTContext cContext, BridgedTypeRepr base, BridgedSourceLoc cEllipsisLoc); +SWIFT_NAME( + "BridgedIntegerTypeRepr.createParsed(_:string:loc:minusLoc:)") +BridgedIntegerTypeRepr BridgedIntegerTypeRepr_createParsed( + BridgedASTContext cContext, BridgedStringRef cString, BridgedSourceLoc cLoc, + BridgedSourceLoc cMinusLoc); + SWIFT_NAME("BridgedTypeRepr.dump(self:)") void BridgedTypeRepr_dump(BridgedTypeRepr type); diff --git a/lib/AST/Bridging/TypeReprBridging.cpp b/lib/AST/Bridging/TypeReprBridging.cpp index b8ff8eee9199c..61eb2ddfa6217 100644 --- a/lib/AST/Bridging/TypeReprBridging.cpp +++ b/lib/AST/Bridging/TypeReprBridging.cpp @@ -298,3 +298,13 @@ BridgedExistentialTypeRepr_createParsed(BridgedASTContext cContext, return new (context) ExistentialTypeRepr(cAnyLoc.unbridged(), baseTy.unbridged()); } + +BridgedIntegerTypeRepr +BridgedIntegerTypeRepr_createParsed(BridgedASTContext cContext, + BridgedStringRef cString, + BridgedSourceLoc cLoc, + BridgedSourceLoc cMinusLoc) { + ASTContext &context = cContext.unbridged(); + return new (context) IntegerTypeRepr(cString.unbridged(), cLoc.unbridged(), + cMinusLoc.unbridged()); +} diff --git a/lib/ASTGen/Sources/ASTGen/Exprs.swift b/lib/ASTGen/Sources/ASTGen/Exprs.swift index 683cebae1c37e..9fa11c239ba3d 100644 --- a/lib/ASTGen/Sources/ASTGen/Exprs.swift +++ b/lib/ASTGen/Sources/ASTGen/Exprs.swift @@ -760,7 +760,7 @@ extension ASTGenVisitor { let generics = node.genericArgumentClause let lAngleLoc = self.generateSourceLoc(generics.leftAngle) let genericArguments = generics.arguments.lazy.map { - self.generate(type: $0.argument) + self.generate(genericArgument: $0.argument) } let rAngleLoc = self.generateSourceLoc(generics.rightAngle) return .createParsed( diff --git a/lib/ASTGen/Sources/ASTGen/Generics.swift b/lib/ASTGen/Sources/ASTGen/Generics.swift index ab6e3449e42bb..34c7e82534300 100644 --- a/lib/ASTGen/Sources/ASTGen/Generics.swift +++ b/lib/ASTGen/Sources/ASTGen/Generics.swift @@ -11,6 +11,8 @@ //===----------------------------------------------------------------------===// import ASTBridging + +@_spi(ExperimentalLanguageFeatures) import SwiftSyntax extension ASTGenVisitor { @@ -72,8 +74,8 @@ extension ASTGenVisitor { return BridgedRequirementRepr( SeparatorLoc: self.generateSourceLoc(sameType.equal), Kind: .sameType, - FirstType: self.generate(type: sameType.leftType), - SecondType: self.generate(type: sameType.rightType) + FirstType: self.generate(sameTypeLeftType: sameType.leftType), + SecondType: self.generate(sameTypeRightType: sameType.rightType) ) case .layoutRequirement(_): // FIXME: Implement layout requirement translation. @@ -87,4 +89,117 @@ extension ASTGenVisitor { requirements: requirements.bridgedArray(in: self) ) } + + func generate(sameTypeLeftType node: SameTypeRequirementSyntax.LeftType) -> BridgedTypeRepr { + switch node { + case .type(let type): + return self.generate(type: type) + + // The only expressions same type left types support right now are + // integer literals, '123', and prefix operators for negative integer + // literals, '-123'. + case .expr(let expr): + switch expr.as(ExprSyntaxEnum.self) { + case .integerLiteralExpr(let node): + return self.generate(integerType: node) + + case .prefixOperatorExpr(let node): + let op = node.operator + + guard op.text == "-" else { + fatalError("Unknown prefix operator for same type left type") + } + + guard case .integerLiteralExpr(let node) = node.expression.as(ExprSyntaxEnum.self) else { + fatalError("Unknown expression kind for same type left type") + } + + return self.generate(integerType: node, minusLoc: self.generateSourceLoc(op)) + + default: + fatalError("Unknown expression kind for same type left type") + } + } + } + + func generate(sameTypeRightType node: SameTypeRequirementSyntax.RightType) -> BridgedTypeRepr { + switch node { + case .type(let type): + return self.generate(type: type) + + // The only expressions same type right types support right now are + // integer literals, '123', and prefix operators for negative integer + // literals, '-123'. + case .expr(let expr): + switch expr.as(ExprSyntaxEnum.self) { + case .integerLiteralExpr(let node): + return self.generate(integerType: node) + + case .prefixOperatorExpr(let node): + let op = node.operator + + guard op.text == "-" else { + fatalError("Unknown prefix operator for same type right type") + } + + guard case .integerLiteralExpr(let node) = node.expression.as(ExprSyntaxEnum.self) else { + fatalError("Unknown expression kind for same type right type") + } + + return self.generate(integerType: node, minusLoc: self.generateSourceLoc(op)) + + default: + fatalError("Unknown expression kind for same type right type") + } + } + } + + func generate(genericArgument node: GenericArgumentSyntax.Argument) -> BridgedTypeRepr { + switch node { + case .type(let type): + return self.generate(type: type) + + // The only expressions generic argument types support right now are + // integer literals, '123', and prefix operators for negative integer + // literals, '-123'. + case .expr(let expr): + switch expr.as(ExprSyntaxEnum.self) { + case .integerLiteralExpr(let node): + return self.generate(integerType: node) + + case .prefixOperatorExpr(let node): + let op = node.operator + + guard op.text == "-" else { + fatalError("Unknown prefix operator for generic argument type") + } + + guard case .integerLiteralExpr(let node) = node.expression.as(ExprSyntaxEnum.self) else { + fatalError("Unknown expression kind for generic argument type") + } + + return self.generate(integerType: node, minusLoc: self.generateSourceLoc(op)) + + default: + fatalError("Unknown expression kind for generic argument type") + } + } + } + + func generate( + integerType node: IntegerLiteralExprSyntax, + minusLoc: BridgedSourceLoc = BridgedSourceLoc() + ) -> BridgedTypeRepr { + var desc = node.trimmedDescription + let str = desc.withBridgedString { + self.ctx.allocateCopy(string: $0) + } + + return BridgedIntegerTypeRepr.createParsed( + self.ctx, + string: str, + loc: self.generateSourceLoc(node), + minusLoc: minusLoc + ).asTypeRepr + } } diff --git a/lib/ASTGen/Sources/ASTGen/Types.swift b/lib/ASTGen/Sources/ASTGen/Types.swift index 45fd24f8caa6b..88ddbd0ab20f7 100644 --- a/lib/ASTGen/Sources/ASTGen/Types.swift +++ b/lib/ASTGen/Sources/ASTGen/Types.swift @@ -120,7 +120,7 @@ extension ASTGenVisitor { } let genericArguments = generics.arguments.lazy.map { - self.generate(type: $0.argument) + self.generate(genericArgument: $0.argument) } return BridgedUnqualifiedIdentTypeRepr.createParsed( @@ -140,7 +140,7 @@ extension ASTGenVisitor { let angleRange: BridgedSourceRange if let generics = node.genericArgumentClause { genericArguments = generics.arguments.lazy.map { - self.generate(type: $0.argument) + self.generate(genericArgument: $0.argument) }.bridgedArray(in: self) angleRange = self.generateSourceRange(start: generics.leftAngle, end: generics.rightAngle) diff --git a/lib/Macros/Sources/SwiftMacros/DistributedResolvableMacro.swift b/lib/Macros/Sources/SwiftMacros/DistributedResolvableMacro.swift index 8982ad965d121..5860df0a3c9a4 100644 --- a/lib/Macros/Sources/SwiftMacros/DistributedResolvableMacro.swift +++ b/lib/Macros/Sources/SwiftMacros/DistributedResolvableMacro.swift @@ -9,6 +9,7 @@ // //===----------------------------------------------------------------------===// +@_spi(ExperimentalLanguageFeatures) import SwiftSyntax import SwiftSyntaxMacros import SwiftDiagnostics @@ -141,10 +142,21 @@ extension DistributedResolvableMacro { specificActorSystemRequirement = conformanceReq.rightType.trimmed isGenericStub = true - case .sameTypeRequirement(let sameTypeReq) - where sameTypeReq.leftType.isActorSystem: - specificActorSystemRequirement = sameTypeReq.rightType.trimmed - isGenericStub = false + case .sameTypeRequirement(let sameTypeReq): + switch sameTypeReq.leftType { + case .type(let type) where type.isActorSystem: + switch sameTypeReq.rightType.trimmed { + case .type(let rightType): + specificActorSystemRequirement = rightType + isGenericStub = false + + case .expr: + fatalError("Expression type not supported for distributed actor") + } + + default: + continue + } default: continue diff --git a/lib/Macros/Sources/SwiftMacros/OptionSetMacro.swift b/lib/Macros/Sources/SwiftMacros/OptionSetMacro.swift index b9594b23191e2..62cc897d336d7 100644 --- a/lib/Macros/Sources/SwiftMacros/OptionSetMacro.swift +++ b/lib/Macros/Sources/SwiftMacros/OptionSetMacro.swift @@ -72,7 +72,7 @@ public struct OptionSetMacro { of attribute: AttributeSyntax, attachedTo decl: Decl, in context: Context - ) -> (StructDeclSyntax, EnumDeclSyntax, TypeSyntax)? { + ) -> (StructDeclSyntax, EnumDeclSyntax, GenericArgumentSyntax.Argument)? { // Determine the name of the options enum. let optionsEnumName: String if case let .argumentList(arguments) = attribute.arguments, From 63eca896b7f5fcd06d4393db6bb819fa00bc059e Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Mon, 21 Oct 2024 16:52:20 -0700 Subject: [PATCH 02/10] Update syntax_macro_definitions.swift --- .../Inputs/syntax_macro_definitions.swift | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/test/Macros/Inputs/syntax_macro_definitions.swift b/test/Macros/Inputs/syntax_macro_definitions.swift index 81a336ee01381..f2fd8ad55685a 100644 --- a/test/Macros/Inputs/syntax_macro_definitions.swift +++ b/test/Macros/Inputs/syntax_macro_definitions.swift @@ -1,6 +1,6 @@ import SwiftDiagnostics import SwiftOperators -import SwiftSyntax +@_spi(ExperimentalLanguageFeatures) import SwiftSyntax import SwiftSyntaxBuilder @_spi(ExperimentalLanguageFeature) import SwiftSyntaxMacros @@ -946,12 +946,25 @@ public struct AddAsyncMacro: PeerMacro { let returnType = completionHandlerParameter.parameters.first?.type let isResultReturn = returnType?.children(viewMode: .all).first?.description == "Result" - let successReturnType = - if isResultReturn { - returnType!.as(IdentifierTypeSyntax.self)!.genericArgumentClause?.arguments.first!.argument - } else { - returnType + + let successReturnType: TypeSyntax? + + if isResultReturn { + let argument = returnType!.as(IdentifierTypeSyntax.self)!.genericArgumentClause?.arguments.first!.argument + + switch argument { + case .some(.type(let type)): + successReturnType = type + + case .some(.expr(_)): + fatalError("expression not available here") + + case .none: + successReturnType = nil } + } else { + successReturnType = returnType + } // Remove completionHandler and comma from the previous parameter var newParameterList = funcDecl.signature.parameterClause.parameters From 5520baeab0e68f907795026276ccd84bd3e1ecf3 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 22 Oct 2024 10:08:11 -0700 Subject: [PATCH 03/10] Address ASTGen feedback --- lib/ASTGen/Sources/ASTGen/Generics.swift | 105 ++++++--------------- lib/ASTGen/Sources/ASTGen/SourceFile.swift | 1 + 2 files changed, 31 insertions(+), 75 deletions(-) diff --git a/lib/ASTGen/Sources/ASTGen/Generics.swift b/lib/ASTGen/Sources/ASTGen/Generics.swift index 34c7e82534300..81a3538286d2e 100644 --- a/lib/ASTGen/Sources/ASTGen/Generics.swift +++ b/lib/ASTGen/Sources/ASTGen/Generics.swift @@ -13,6 +13,7 @@ import ASTBridging @_spi(ExperimentalLanguageFeatures) +@_spi(RawSyntax) import SwiftSyntax extension ASTGenVisitor { @@ -95,30 +96,8 @@ extension ASTGenVisitor { case .type(let type): return self.generate(type: type) - // The only expressions same type left types support right now are - // integer literals, '123', and prefix operators for negative integer - // literals, '-123'. case .expr(let expr): - switch expr.as(ExprSyntaxEnum.self) { - case .integerLiteralExpr(let node): - return self.generate(integerType: node) - - case .prefixOperatorExpr(let node): - let op = node.operator - - guard op.text == "-" else { - fatalError("Unknown prefix operator for same type left type") - } - - guard case .integerLiteralExpr(let node) = node.expression.as(ExprSyntaxEnum.self) else { - fatalError("Unknown expression kind for same type left type") - } - - return self.generate(integerType: node, minusLoc: self.generateSourceLoc(op)) - - default: - fatalError("Unknown expression kind for same type left type") - } + return self.generateIntegerType(expr: expr).asTypeRepr } } @@ -127,30 +106,8 @@ extension ASTGenVisitor { case .type(let type): return self.generate(type: type) - // The only expressions same type right types support right now are - // integer literals, '123', and prefix operators for negative integer - // literals, '-123'. case .expr(let expr): - switch expr.as(ExprSyntaxEnum.self) { - case .integerLiteralExpr(let node): - return self.generate(integerType: node) - - case .prefixOperatorExpr(let node): - let op = node.operator - - guard op.text == "-" else { - fatalError("Unknown prefix operator for same type right type") - } - - guard case .integerLiteralExpr(let node) = node.expression.as(ExprSyntaxEnum.self) else { - fatalError("Unknown expression kind for same type right type") - } - - return self.generate(integerType: node, minusLoc: self.generateSourceLoc(op)) - - default: - fatalError("Unknown expression kind for same type right type") - } + return self.generateIntegerType(expr: expr).asTypeRepr } } @@ -159,47 +116,45 @@ extension ASTGenVisitor { case .type(let type): return self.generate(type: type) - // The only expressions generic argument types support right now are - // integer literals, '123', and prefix operators for negative integer - // literals, '-123'. case .expr(let expr): - switch expr.as(ExprSyntaxEnum.self) { - case .integerLiteralExpr(let node): - return self.generate(integerType: node) + return self.generateIntegerType(expr: expr).asTypeRepr + } + } - case .prefixOperatorExpr(let node): - let op = node.operator + func generateIntegerType(expr node: ExprSyntax) -> BridgedIntegerTypeRepr { + var minusLoc = BridgedSourceLoc() + let literalExpr: IntegerLiteralExprSyntax - guard op.text == "-" else { - fatalError("Unknown prefix operator for generic argument type") - } + // The only expressions generic argument types support right now are + // integer literals, '123', and prefix operators for negative integer + // literals, '-123'. + switch node.as(ExprSyntaxEnum.self) { + case .integerLiteralExpr(let node): + literalExpr = node - guard case .integerLiteralExpr(let node) = node.expression.as(ExprSyntaxEnum.self) else { - fatalError("Unknown expression kind for generic argument type") - } + case .prefixOperatorExpr(let node): + let op = node.operator - return self.generate(integerType: node, minusLoc: self.generateSourceLoc(op)) + guard op.text == "-" else { + fatalError("Unknown prefix operator for generic argument type") + } - default: + guard let node = node.expression.as(IntegerLiteralExprSyntax.self) else { fatalError("Unknown expression kind for generic argument type") } - } - } - func generate( - integerType node: IntegerLiteralExprSyntax, - minusLoc: BridgedSourceLoc = BridgedSourceLoc() - ) -> BridgedTypeRepr { - var desc = node.trimmedDescription - let str = desc.withBridgedString { - self.ctx.allocateCopy(string: $0) + minusLoc = self.generateSourceLoc(op) + literalExpr = node + + default: + fatalError("Unknown expression kind for generic argument type") } - return BridgedIntegerTypeRepr.createParsed( + return .createParsed( self.ctx, - string: str, - loc: self.generateSourceLoc(node), + string: self.copyAndStripUnderscores(text: literalExpr.literal.rawText), + loc: self.generateSourceLoc(literalExpr), minusLoc: minusLoc - ).asTypeRepr + ) } } diff --git a/lib/ASTGen/Sources/ASTGen/SourceFile.swift b/lib/ASTGen/Sources/ASTGen/SourceFile.swift index 7243f55fa5e4a..8684a51c85aa8 100644 --- a/lib/ASTGen/Sources/ASTGen/SourceFile.swift +++ b/lib/ASTGen/Sources/ASTGen/SourceFile.swift @@ -75,6 +75,7 @@ extension Parser.ExperimentalFeatures { mapFeature(.NonescapableTypes, to: .nonescapableTypes) mapFeature(.TrailingComma, to: .trailingComma) mapFeature(.CoroutineAccessors, to: .coroutineAccessors) + mapFeature(.ValueGenerics, to: .valueGenerics) } } From 90ce2cd361c48abc5ff38cddff66334d4a9e64ac Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Wed, 18 Sep 2024 10:30:10 -0700 Subject: [PATCH 04/10] Restrict parsing integer types in certain contexts --- include/swift/Parse/Parser.h | 5 +++++ lib/Parse/ParseGeneric.cpp | 8 +++++-- lib/Parse/ParseType.cpp | 40 +++++++++++++++++++++++----------- test/Parse/integer_types.swift | 24 ++++++++++++++++++-- test/Sema/value_generics.swift | 13 ++++++----- 5 files changed, 68 insertions(+), 22 deletions(-) diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index c94dbde85b4ba..7c59e027d8cbe 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -1411,6 +1411,11 @@ class Parser { ParserResult parseTypeSimple( Diag<> MessageID, ParseTypeReason reason); + ParserResult parseTypeOrValue(); + ParserResult parseTypeOrValue(Diag<> MessageID, + ParseTypeReason reason = ParseTypeReason::Unspecified, + bool fromASTGen = false); + /// Parse layout constraint. LayoutConstraint parseLayoutConstraint(Identifier LayoutConstraintID); diff --git a/lib/Parse/ParseGeneric.cpp b/lib/Parse/ParseGeneric.cpp index ffd84b5ea50df..818e3bab7f79e 100644 --- a/lib/Parse/ParseGeneric.cpp +++ b/lib/Parse/ParseGeneric.cpp @@ -317,7 +317,9 @@ ParserStatus Parser::parseGenericWhereClause( // Parse the leading type. It doesn't necessarily have to be just a type // identifier if we're dealing with a same-type constraint. - ParserResult FirstType = parseType(); + // + // Note: This can be a value type, e.g. '123 == N' or 'N == 123'. + ParserResult FirstType = parseTypeOrValue(); if (FirstType.hasCodeCompletion()) { Status.setHasCodeCompletionAndIsError(); @@ -377,7 +379,9 @@ ParserStatus Parser::parseGenericWhereClause( SourceLoc EqualLoc = consumeToken(); // Parse the second type. - ParserResult SecondType = parseType(); + // + // Note: This can be a value type, e.g. '123 == N' or 'N == 123'. + ParserResult SecondType = parseTypeOrValue(); Status |= SecondType; if (SecondType.isNull()) SecondType = makeParserResult(ErrorTypeRepr::create(Context, PreviousLoc)); diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp index df4bd5f4a996a..aba645461a011 100644 --- a/lib/Parse/ParseType.cpp +++ b/lib/Parse/ParseType.cpp @@ -175,12 +175,6 @@ ParserResult Parser::parseTypeSimple( tildeLoc = consumeToken(); } - // Eat any '-' preceding integer literals. - SourceLoc minusLoc; - if (Tok.isMinus() && peekToken().is(tok::integer_literal)) { - minusLoc = consumeToken(); - } - switch (Tok.getKind()) { case tok::kw_Self: case tok::identifier: @@ -237,12 +231,6 @@ ParserResult Parser::parseTypeSimple( } return makeParserCodeCompletionResult( ErrorTypeRepr::create(Context, consumeToken(tok::code_complete))); - case tok::integer_literal: { - auto text = copyAndStripUnderscores(Tok.getText()); - auto loc = consumeToken(tok::integer_literal); - ty = makeParserResult(new (Context) IntegerTypeRepr(text, loc, minusLoc)); - break; - } case tok::l_square: { ty = parseTypeCollection(); break; @@ -739,7 +727,8 @@ ParserStatus Parser::parseGenericArguments(SmallVectorImpl &Args, // variadic generic types. if (!startsWithGreater(Tok)) { while (true) { - ParserResult Ty = parseType(diag::expected_type); + // Note: This can be a value type, e.g. 'Vector<3, Int>'. + ParserResult Ty = parseTypeOrValue(diag::expected_type); if (Ty.isNull() || Ty.hasCodeCompletion()) { // Skip until we hit the '>'. RAngleLoc = skipUntilGreaterInTypeList(); @@ -1481,6 +1470,31 @@ Parser::parseTypeImplicitlyUnwrappedOptional(ParserResult base) { return makeParserResult(ParserStatus(base), TyR); } +ParserResult Parser::parseTypeOrValue() { + return parseTypeOrValue(diag::expected_type); +} + +ParserResult Parser::parseTypeOrValue(Diag<> MessageID, + ParseTypeReason reason, + bool fromASTGen) { + // Eat any '-' preceding integer literals. + SourceLoc minusLoc; + if (Tok.isMinus() && peekToken().is(tok::integer_literal)) { + minusLoc = consumeToken(); + } + + // Attempt to parse values first. Right now the only value that can be parsed + // as a type are integers. + if (Tok.is(tok::integer_literal)) { + auto text = copyAndStripUnderscores(Tok.getText()); + auto loc = consumeToken(tok::integer_literal); + return makeParserResult(new (Context) IntegerTypeRepr(text, loc, minusLoc)); + } + + // Otherwise, attempt to parse a regular type. + return parseType(MessageID, reason, fromASTGen); +} + //===----------------------------------------------------------------------===// // Speculative type list parsing //===----------------------------------------------------------------------===// diff --git a/test/Parse/integer_types.swift b/test/Parse/integer_types.swift index 3ac09e87669ff..8d4ec0f4be092 100644 --- a/test/Parse/integer_types.swift +++ b/test/Parse/integer_types.swift @@ -1,8 +1,12 @@ // RUN: %target-typecheck-verify-swift -let a: 123 // expected-error {{integer unexpectedly used in a type position}} +let a: 123 // expected-error {{consecutive statements on a line must be separated by ';'}} + // expected-error@-1 {{expected type}} + // expected-warning@-2 {{integer literal is unused}} -let b: -123 // expected-error {{integer unexpectedly used in a type position}} +let b: -123 // expected-error {{consecutive statements on a line must be separated by ';'}} + // expected-error@-1 {{expected type}} + // expected-warning@-2 {{integer literal is unused}} let c: -Int // expected-error {{expected type}} // expected-error@-1 {{consecutive statements on a line must be separated by ';'}} @@ -30,3 +34,19 @@ let f = Generic<-Int>.self // expected-error {{generic parameter 'T' could not b // expected-error@-1 {{missing whitespace between '<' and '-' operators}} // expected-error@-2 {{'>' is not a postfix unary operator}} // expected-note@-3 {{explicitly specify the generic arguments to fix this issue}} + +let g: 123.Type // expected-error {{consecutive statements on a line must be separated by ';'}} + // expected-error@-1 {{expected type}} + // expected-error@-2 {{value of type 'Int' has no member 'Type'}} + +let h: 123.Protocol // expected-error {{consecutive statements on a line must be separated by ';'}} + // expected-error@-1 {{expected type}} + // expected-error@-2 {{value of type 'Int' has no member 'Protocol'}} + +let i: 123? // expected-error {{consecutive statements on a line must be separated by ';'}} + // expected-error@-1 {{expected type}} + // expected-error@-2 {{cannot use optional chaining on non-optional value of type 'Int'}} + +let j: 123! // expected-error {{consecutive statements on a line must be separated by ';'}} + // expected-error@-1 {{expected type}} + // expected-error@-2 {{cannot force unwrap value of non-optional type 'Int'}} diff --git a/test/Sema/value_generics.swift b/test/Sema/value_generics.swift index 842c24a70f75f..46c6a7fc7d360 100644 --- a/test/Sema/value_generics.swift +++ b/test/Sema/value_generics.swift @@ -53,18 +53,21 @@ struct Generic {} struct GenericWithIntParam {} extension Generic where T == 123 {} // expected-error {{cannot constrain type parameter 'T' to be integer '123'}} -extension Generic where T == 123.Type {} // expected-error {{integer unexpectedly used in a type position}} +extension Generic where T == 123.Type {} // expected-error {{cannot constrain type parameter 'T' to be integer '123'}} + // expected-error@-1 {{expected '{' in extension}} +extension Generic where T == 123? {} // expected-error {{cannot constrain type parameter 'T' to be integer '123'}} + // expected-error@-1 {{expected '{' in extension}} func f(_: Generic<123>) {} // expected-error {{integer unexpectedly used in a type position}} func g(_: Generic) {} // expected-error {{cannot use value type 'N' for generic argument 'T'}} -func h(_: (Int, 123)) {} // expected-error {{integer unexpectedly used in a type position}} -func i(_: () -> 123) {} // expected-error {{integer unexpectedly used in a type position}} +func h(_: (Int, 123)) {} // expected-error {{expected type}} +func i(_: () -> 123) {} // expected-error {{expected type}} func j(_: (A<123>) -> ()) {} // OK -func k(_: some 123) {} // expected-error {{integer unexpectedly used in a type position}} +func k(_: some 123) {} // expected-error {{expected parameter type following ':'}} func l(_: GenericWithIntParam<123, Int>) {} // expected-error {{cannot pass type 'Int' as a value for generic value 'N'}} func m(_: GenericWithIntParam) {} // OK -typealias One = 1 // expected-error {{integer unexpectedly used in a type position}} +typealias One = 1 // expected-error {{expected type in type alias declaration}} struct B {} // expected-error {{'UInt8' is not a supported value type for 'N'}} From 8b1d08e008d869205ad630285534d7e5487b1be7 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Wed, 18 Sep 2024 13:14:19 -0700 Subject: [PATCH 05/10] Allow raw layout to parse integer types --- lib/Parse/ParseDecl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 9d99226b24bdc..ff4a77d339647 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3963,7 +3963,7 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes, return makeParserSuccess(); } - auto countType = parseType(diag::expected_type); + auto countType = parseTypeOrValue(diag::expected_type); if (countType.isNull()) { return makeParserSuccess(); } From ac1d15e0b011cdcda33fbdbfd24433b6ad1d6afb Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Thu, 19 Sep 2024 11:16:22 -0700 Subject: [PATCH 06/10] Explicitly call parseTypeOrValue for type value instructions --- lib/SIL/Parser/ParseSIL.cpp | 38 ++++++++++++++++++++++++++++++++++++- lib/SIL/Parser/SILParser.h | 5 +++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/lib/SIL/Parser/ParseSIL.cpp b/lib/SIL/Parser/ParseSIL.cpp index 5250f62414992..41e4b70790654 100644 --- a/lib/SIL/Parser/ParseSIL.cpp +++ b/lib/SIL/Parser/ParseSIL.cpp @@ -1067,6 +1067,42 @@ bool SILParser::parseASTType(CanType &result, return false; } +bool SILParser::parseASTTypeOrValue(CanType &result, + GenericSignature genericSig, + GenericParamList *genericParams, + bool forceContextualType) { + auto parsedType = P.parseTypeOrValue(); + if (parsedType.isNull()) return true; + + // If we weren't given a specific generic context to resolve the type + // within, use the contextual generic parameters and always produce + // a contextual type. Otherwise, produce a contextual type only if + // we were asked for one. + bool wantContextualType = forceContextualType; + if (!genericSig) { + genericSig = ContextGenericSig; + wantContextualType = true; + } + if (genericParams == nullptr) + genericParams = ContextGenericParams; + + bindSILGenericParams(parsedType.get()); + + auto resolvedType = performTypeResolution( + parsedType.get(), /*isSILType=*/false, genericSig, genericParams); + if (wantContextualType && genericSig) { + resolvedType = genericSig.getGenericEnvironment() + ->mapTypeIntoContext(resolvedType); + } + + if (resolvedType->hasError()) + return true; + + result = resolvedType->getCanonicalType(); + + return false; +} + void SILParser::bindSILGenericParams(TypeRepr *TyR) { // Resolve the generic environments for parsed generic function and box types. class HandleSILGenericParamsWalker : public ASTWalker { @@ -3122,7 +3158,7 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B, CanType paramType; if (parseSILType(Ty) || parseVerbatim("for") || - parseASTType(paramType)) + parseASTTypeOrValue(paramType)) return true; ResultVal = B.createTypeValue(InstLoc, Ty, paramType); diff --git a/lib/SIL/Parser/SILParser.h b/lib/SIL/Parser/SILParser.h index 9a6c90f089ce6..df1a75543b881 100644 --- a/lib/SIL/Parser/SILParser.h +++ b/lib/SIL/Parser/SILParser.h @@ -235,6 +235,11 @@ class SILParser { return false; } + bool parseASTTypeOrValue(CanType &result, + GenericSignature genericSig = GenericSignature(), + GenericParamList *genericParams = nullptr, + bool forceContextualType = false); + std::optional parseOptionalAttribute(ArrayRef expected) { // We parse here @ . From 0b108e2cd20c9088cf03b05bbdd3c0296bfe7adb Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 24 Sep 2024 11:02:52 -0700 Subject: [PATCH 07/10] Update tests to old behavior --- test/attr/attr_implements_bad_parse.swift | 2 +- test/expr/postfix/init/unqualified.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/attr/attr_implements_bad_parse.swift b/test/attr/attr_implements_bad_parse.swift index 17f0deb0bfe34..82f7f990d1709 100644 --- a/test/attr/attr_implements_bad_parse.swift +++ b/test/attr/attr_implements_bad_parse.swift @@ -1,7 +1,7 @@ // RUN: %target-swift-frontend -parse -verify %s struct S0 { - @_implements(1, Foo) // OK. We can parse integers as types now, so this is fine. We will diagnose its incorrect usage during type checking. + @_implements(1, Foo) // expected-error {{expected type}} func f() { } } diff --git a/test/expr/postfix/init/unqualified.swift b/test/expr/postfix/init/unqualified.swift index 645bef69ec32b..bb8372378d2c2 100644 --- a/test/expr/postfix/init/unqualified.swift +++ b/test/expr/postfix/init/unqualified.swift @@ -62,7 +62,7 @@ class Theodosia: Aaron { // FIXME: We could optimistically parse this as an expression instead // expected-error@+2 {{initializers may only be declared within a type}} - // expected-error@+1 {{integer unexpectedly used in a type position}} + // expected-error@+1 {{expected parameter type following ':'}} init(z: 0) } @@ -98,7 +98,7 @@ struct AaronStruct { // FIXME: We could optimistically parse this as an expression instead // expected-error@+2 {{initializers may only be declared within a type}} - // expected-error@+1 {{integer unexpectedly used in a type position}} + // expected-error@+1 {{expected parameter type following ':'}} init(y: 1) } From 400bfb227c6116d3bfb1b1971e0bc5538c4cd553 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 22 Oct 2024 10:54:46 -0700 Subject: [PATCH 08/10] Remove disable parser round trip on some tests --- test/Interpreter/value_generics.swift | 3 +-- test/ModuleInterface/value_generics.swift | 5 ++--- test/Sema/value_generics.swift | 3 +-- test/Serialization/value_generics.swift | 3 +-- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/test/Interpreter/value_generics.swift b/test/Interpreter/value_generics.swift index ae576deabe845..e6db8bbfe57eb 100644 --- a/test/Interpreter/value_generics.swift +++ b/test/Interpreter/value_generics.swift @@ -1,5 +1,4 @@ -// RUN: %target-run-simple-swift(-enable-experimental-feature ValueGenerics -Xfrontend -disable-availability-checking -Xfrontend -disable-experimental-parser-round-trip) | %FileCheck %s -// FIXME: Remove -disable-experimental-parser-round-trip after https://github.com/swiftlang/swift-syntax/pull/2859 is merged +// RUN: %target-run-simple-swift(-enable-experimental-feature ValueGenerics -Xfrontend -disable-availability-checking) | %FileCheck %s // UNSUPPORTED: use_os_stdlib // UNSUPPORTED: back_deployment_runtime diff --git a/test/ModuleInterface/value_generics.swift b/test/ModuleInterface/value_generics.swift index c5cea60129df6..51784a09225b9 100644 --- a/test/ModuleInterface/value_generics.swift +++ b/test/ModuleInterface/value_generics.swift @@ -1,7 +1,6 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s -module-name ValueGeneric -enable-experimental-feature ValueGenerics -disable-availability-checking -disable-experimental-parser-round-trip -// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -module-name ValueGeneric -disable-availability-checking -disable-experimental-parser-round-trip -// FIXME: Remove -disable-experimental-parser-round-trip after https://github.com/swiftlang/swift-syntax/pull/2859 is merged +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s -module-name ValueGeneric -enable-experimental-feature ValueGenerics -disable-availability-checking +// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -module-name ValueGeneric -disable-availability-checking // RUN: %FileCheck %s < %t.swiftinterface // REQUIRES: swift_feature_ValueGenerics diff --git a/test/Sema/value_generics.swift b/test/Sema/value_generics.swift index 46c6a7fc7d360..44c17d5190e40 100644 --- a/test/Sema/value_generics.swift +++ b/test/Sema/value_generics.swift @@ -1,5 +1,4 @@ -// RUN: %target-typecheck-verify-swift -enable-experimental-feature ValueGenerics -enable-experimental-feature NonescapableTypes -disable-availability-checking -disable-experimental-parser-round-trip -// FIXME: Remove -disable-experimental-parser-round-trip after https://github.com/swiftlang/swift-syntax/pull/2859 is merged +// RUN: %target-typecheck-verify-swift -enable-experimental-feature ValueGenerics -enable-experimental-feature NonescapableTypes -disable-availability-checking // REQUIRES: swift_feature_NonescapableTypes // REQUIRES: swift_feature_ValueGenerics diff --git a/test/Serialization/value_generics.swift b/test/Serialization/value_generics.swift index 0f08758a489e7..c26fcf016b573 100644 --- a/test/Serialization/value_generics.swift +++ b/test/Serialization/value_generics.swift @@ -1,6 +1,5 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend %s -emit-module -enable-experimental-feature ValueGenerics -enable-experimental-feature RawLayout -disable-availability-checking -disable-experimental-parser-round-trip -parse-as-library -o %t -// FIXME: Remove -disable-experimental-parser-round-trip after https://github.com/swiftlang/swift-syntax/pull/2859 is merged +// RUN: %target-swift-frontend %s -emit-module -enable-experimental-feature ValueGenerics -enable-experimental-feature RawLayout -disable-availability-checking -parse-as-library -o %t // RUN: %target-sil-opt -enable-sil-verify-all %t/value_generics.swiftmodule -o - | %FileCheck %s // REQUIRES: swift_feature_RawLayout From eed695d67964a5a0f4717eb7a2503c7013fb5eda Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Mon, 28 Oct 2024 10:53:27 -0700 Subject: [PATCH 09/10] Add some ASTGen tests --- .../Sources/SwiftMacros/DistributedResolvableMacro.swift | 7 ++++++- test/ASTGen/decls.swift | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/Macros/Sources/SwiftMacros/DistributedResolvableMacro.swift b/lib/Macros/Sources/SwiftMacros/DistributedResolvableMacro.swift index 5860df0a3c9a4..858a4aa772642 100644 --- a/lib/Macros/Sources/SwiftMacros/DistributedResolvableMacro.swift +++ b/lib/Macros/Sources/SwiftMacros/DistributedResolvableMacro.swift @@ -151,7 +151,11 @@ extension DistributedResolvableMacro { isGenericStub = false case .expr: - fatalError("Expression type not supported for distributed actor") + throw DiagnosticsError( + syntax: sameTypeReq.rightType, + message: "Expression type not supported for distributed actor", + id: .invalidGenericArgument + ) } default: @@ -277,6 +281,7 @@ struct DistributedResolvableMacroDiagnostic: DiagnosticMessage { enum ID: String { case invalidApplication = "invalid type" case missingInitializer = "missing initializer" + case invalidGenericArgument = "invalid generic argument" } var message: String diff --git a/test/ASTGen/decls.swift b/test/ASTGen/decls.swift index f6697ccc8d4e9..2d56973949363 100644 --- a/test/ASTGen/decls.swift +++ b/test/ASTGen/decls.swift @@ -291,3 +291,12 @@ struct ValueStruct {} func genericTest1(_: T) {} func genericTest2(_: repeat each T) {} func genericTest4(_: ValueStruct) {} + +func concreteValueTest1(_: ValueStruct<123>) {} +func concreteValueTest2(_: ValueStruct<-123>) {} + +extension ValueStruct where N == 123 {} +extension ValueStruct where 123 == N {} +extension ValueStruct where N == -123 {} +extension ValueStruct where -123 == N {} + From 13406e3b583102960be0b9715d2fb6b767b89a73 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Mon, 4 Nov 2024 17:14:39 -0800 Subject: [PATCH 10/10] Update Exprs.swift --- lib/ASTGen/Sources/ASTGen/Exprs.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ASTGen/Sources/ASTGen/Exprs.swift b/lib/ASTGen/Sources/ASTGen/Exprs.swift index 9fa11c239ba3d..cfa751cbef7cf 100644 --- a/lib/ASTGen/Sources/ASTGen/Exprs.swift +++ b/lib/ASTGen/Sources/ASTGen/Exprs.swift @@ -659,7 +659,7 @@ extension ASTGenVisitor { if let generics = node.genericArgumentClause { leftAngleLoc = self.generateSourceLoc(generics.leftAngle) genericArgs = generics.arguments.map { - self.generate(type: $0.argument) + self.generate(genericArgument: $0.argument) } rightAngleLoc = self.generateSourceLoc(generics.rightAngle) } else {