[ASTGen] Generate 'IsExpansionPattern' generic requirements

E.g. `where repeat each T: Comparable`
This commit is contained in:
Rintaro Ishizaki
2025-03-05 21:48:54 -08:00
parent c8bbfda7eb
commit a506bae136
5 changed files with 55 additions and 34 deletions

View File

@@ -2885,29 +2885,27 @@ struct BridgedRequirementRepr {
BridgedNullableTypeRepr SecondType; BridgedNullableTypeRepr SecondType;
BridgedLayoutConstraint LayoutConstraint; BridgedLayoutConstraint LayoutConstraint;
BridgedSourceLoc LayoutConstraintLoc; BridgedSourceLoc LayoutConstraintLoc;
bool IsExpansionPattern;
// TODO: bool IsExpansionPattern;
swift::RequirementRepr unbridged() const; swift::RequirementRepr unbridged() const;
}; };
SWIFT_NAME( SWIFT_NAME("BridgedRequirementRepr.createTypeConstraint(subject:colonLoc:"
"BridgedRequirementRepr.createTypeConstraint(subject:colonLoc:constraint:)") "constraint:isExpansionPattern:)")
BridgedRequirementRepr BridgedRequirementRepr BridgedRequirementRepr_createTypeConstraint(
BridgedRequirementRepr_createTypeConstraint(BridgedTypeRepr cSubject, BridgedTypeRepr cSubject, BridgedSourceLoc cColonLoc,
BridgedSourceLoc cColonLoc, BridgedTypeRepr cConstraint, bool isExpansionPattern);
BridgedTypeRepr cConstraint); SWIFT_NAME("BridgedRequirementRepr.createSameType(firstType:equalLoc:"
SWIFT_NAME( "secondType:isExpansionPattern:)")
"BridgedRequirementRepr.createSameType(firstType:equalLoc:secondType:)") BridgedRequirementRepr BridgedRequirementRepr_createSameType(
BridgedRequirementRepr BridgedTypeRepr cFirstType, BridgedSourceLoc cEqualLoc,
BridgedRequirementRepr_createSameType(BridgedTypeRepr cFirstType, BridgedTypeRepr cSecondType, bool isExpansionPattern);
BridgedSourceLoc cEqualLoc,
BridgedTypeRepr cSecondType);
SWIFT_NAME("BridgedRequirementRepr.createLayoutConstraint(subject:colonLoc:" SWIFT_NAME("BridgedRequirementRepr.createLayoutConstraint(subject:colonLoc:"
"layout:layoutLoc:)") "layout:layoutLoc:isExpansionPattern:)")
BridgedRequirementRepr BridgedRequirementRepr_createLayoutConstraint( BridgedRequirementRepr BridgedRequirementRepr_createLayoutConstraint(
BridgedTypeRepr cSubject, BridgedSourceLoc cColonLoc, BridgedTypeRepr cSubject, BridgedSourceLoc cColonLoc,
BridgedLayoutConstraint cLayout, BridgedSourceLoc cLayoutLoc); BridgedLayoutConstraint cLayout, BridgedSourceLoc cLayoutLoc,
bool isExpansionPattern);
enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedGenericTypeParamKind : size_t { enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedGenericTypeParamKind : size_t {
/// A regular generic type parameter: 'T' /// A regular generic type parameter: 'T'

View File

@@ -101,23 +101,22 @@ RequirementRepr BridgedRequirementRepr::unbridged() const {
case BridgedRequirementReprKindTypeConstraint: case BridgedRequirementReprKindTypeConstraint:
return RequirementRepr::getTypeConstraint( return RequirementRepr::getTypeConstraint(
FirstType.unbridged(), SeparatorLoc.unbridged(), SecondType.unbridged(), FirstType.unbridged(), SeparatorLoc.unbridged(), SecondType.unbridged(),
/*IsExpansionPattern=*/false); IsExpansionPattern);
case BridgedRequirementReprKindSameType: case BridgedRequirementReprKindSameType:
return RequirementRepr::getSameType( return RequirementRepr::getSameType(
FirstType.unbridged(), SeparatorLoc.unbridged(), SecondType.unbridged(), FirstType.unbridged(), SeparatorLoc.unbridged(), SecondType.unbridged(),
/*IsExpansionPattern=*/false); IsExpansionPattern);
case BridgedRequirementReprKindLayoutConstraint: case BridgedRequirementReprKindLayoutConstraint:
return RequirementRepr::getLayoutConstraint( return RequirementRepr::getLayoutConstraint(
FirstType.unbridged(), SeparatorLoc.unbridged(), FirstType.unbridged(), SeparatorLoc.unbridged(),
{LayoutConstraint.unbridged(), LayoutConstraintLoc.unbridged()}, {LayoutConstraint.unbridged(), LayoutConstraintLoc.unbridged()},
/*IsExpansionPattern=*/false); IsExpansionPattern);
} }
} }
BridgedRequirementRepr BridgedRequirementRepr BridgedRequirementRepr_createTypeConstraint(
BridgedRequirementRepr_createTypeConstraint(BridgedTypeRepr cSubject, BridgedTypeRepr cSubject, BridgedSourceLoc cColonLoc,
BridgedSourceLoc cColonLoc, BridgedTypeRepr cConstraint, bool isExpansionPattern) {
BridgedTypeRepr cConstraint) {
return { return {
/*SeparatorLoc=*/cColonLoc, /*SeparatorLoc=*/cColonLoc,
/*Kind=*/BridgedRequirementReprKindTypeConstraint, /*Kind=*/BridgedRequirementReprKindTypeConstraint,
@@ -125,13 +124,13 @@ BridgedRequirementRepr_createTypeConstraint(BridgedTypeRepr cSubject,
/*SecondType=*/cConstraint.unbridged(), /*SecondType=*/cConstraint.unbridged(),
/*LayoutConstraint=*/{}, /*LayoutConstraint=*/{},
/*LayoutConstraintLoc=*/{}, /*LayoutConstraintLoc=*/{},
/*IsExpansionPattern=*/isExpansionPattern,
}; };
} }
BridgedRequirementRepr BridgedRequirementRepr BridgedRequirementRepr_createSameType(
BridgedRequirementRepr_createSameType(BridgedTypeRepr cFirstType, BridgedTypeRepr cFirstType, BridgedSourceLoc cEqualLoc,
BridgedSourceLoc cEqualLoc, BridgedTypeRepr cSecondType, bool isExpansionPattern) {
BridgedTypeRepr cSecondType) {
return { return {
/*SeparatorLoc=*/cEqualLoc, /*SeparatorLoc=*/cEqualLoc,
/*Kind=*/BridgedRequirementReprKindSameType, /*Kind=*/BridgedRequirementReprKindSameType,
@@ -139,12 +138,14 @@ BridgedRequirementRepr_createSameType(BridgedTypeRepr cFirstType,
/*SecondType=*/cSecondType.unbridged(), /*SecondType=*/cSecondType.unbridged(),
/*LayoutConstraint=*/{}, /*LayoutConstraint=*/{},
/*LayoutConstraintLoc=*/{}, /*LayoutConstraintLoc=*/{},
/*IsExpansionPattern=*/isExpansionPattern,
}; };
} }
BridgedRequirementRepr BridgedRequirementRepr_createLayoutConstraint( BridgedRequirementRepr BridgedRequirementRepr_createLayoutConstraint(
BridgedTypeRepr cSubject, BridgedSourceLoc cColonLoc, BridgedTypeRepr cSubject, BridgedSourceLoc cColonLoc,
BridgedLayoutConstraint cLayout, BridgedSourceLoc cLayoutLoc) { BridgedLayoutConstraint cLayout, BridgedSourceLoc cLayoutLoc,
bool isExpansionPattern) {
return { return {
/*SeparatorLoc=*/cColonLoc, /*SeparatorLoc=*/cColonLoc,
/*Kind=*/BridgedRequirementReprKindLayoutConstraint, /*Kind=*/BridgedRequirementReprKindLayoutConstraint,
@@ -152,6 +153,7 @@ BridgedRequirementRepr BridgedRequirementRepr_createLayoutConstraint(
/*SecondType=*/nullptr, /*SecondType=*/nullptr,
/*LayoutConstraint=*/cLayout, /*LayoutConstraint=*/cLayout,
/*LayoutConstraintLoc=*/cLayoutLoc, /*LayoutConstraintLoc=*/cLayoutLoc,
/*IsExpansionPattern=*/isExpansionPattern,
}; };
} }

View File

@@ -111,25 +111,41 @@ extension ASTGenVisitor {
func generate(genericWhereClause node: GenericWhereClauseSyntax) -> BridgedTrailingWhereClause { func generate(genericWhereClause node: GenericWhereClauseSyntax) -> BridgedTrailingWhereClause {
let requirements = node.requirements.lazy.map { elem -> BridgedRequirementRepr in let requirements = node.requirements.lazy.map { elem -> BridgedRequirementRepr in
// Unwrap 'repeat T' to (isRequirementExpansion: true, type: T)
func generateIsExpansionPattern<Node: SyntaxProtocol>(type node: Node) -> (isExpansionPattern: Bool, type: Node) {
if let expansion = node.as(PackExpansionTypeSyntax.self) {
// Force unwrapping is safe because both 'TypeSyntax' and 'SameTypeRequirementSyntax.LeftType' accept 'TypeSyntax'.
return (true, Node(expansion.repetitionPattern)!)
}
return (false, node)
}
switch elem.requirement { switch elem.requirement {
case .conformanceRequirement(let conformance): case .conformanceRequirement(let conformance):
let (isExpansionPattern, leftType) = generateIsExpansionPattern(type: conformance.leftType)
return .createTypeConstraint( return .createTypeConstraint(
subject: self.generate(type: conformance.leftType), subject: self.generate(type: leftType),
colonLoc: self.generateSourceLoc(conformance.colon), colonLoc: self.generateSourceLoc(conformance.colon),
constraint: self.generate(type: conformance.rightType) constraint: self.generate(type: conformance.rightType),
isExpansionPattern: isExpansionPattern
) )
case .sameTypeRequirement(let sameType): case .sameTypeRequirement(let sameType):
let (isExpansionPattern, leftType) = generateIsExpansionPattern(type: sameType.leftType)
return .createSameType( return .createSameType(
firstType: self.generate(sameTypeLeftType: sameType.leftType), firstType: self.generate(sameTypeLeftType: leftType),
equalLoc: self.generateSourceLoc(sameType.equal), equalLoc: self.generateSourceLoc(sameType.equal),
secondType: self.generate(sameTypeRightType: sameType.rightType) secondType: self.generate(sameTypeRightType: sameType.rightType),
isExpansionPattern: isExpansionPattern
) )
case .layoutRequirement(let layout): case .layoutRequirement(let layout):
let (isExpansionPattern, leftType) = generateIsExpansionPattern(type: layout.type)
return .createLayoutConstraint( return .createLayoutConstraint(
subject: self.generate(type: layout.type), subject: self.generate(type: leftType),
colonLoc: self.generateSourceLoc(layout.colon), colonLoc: self.generateSourceLoc(layout.colon),
layout: self.generate(layoutRequirement: layout), layout: self.generate(layoutRequirement: layout),
layoutLoc: self.generateSourceLoc(layout.layoutSpecifier) layoutLoc: self.generateSourceLoc(layout.layoutSpecifier),
isExpansionPattern: isExpansionPattern
) )
} }
} }

View File

@@ -346,3 +346,5 @@ func testBuilder() {
1 1
} }
} }
struct ExpansionRequirementTest<each T> where repeat each T: Comparable {}

View File

@@ -33,3 +33,6 @@ struct S {
subscript(x: Int) { _ = 1 } // expected-error@:23 {{expected '->' and return type in subscript}} subscript(x: Int) { _ = 1 } // expected-error@:23 {{expected '->' and return type in subscript}}
// expected-note@-1:23 {{insert '->' and return type}} // expected-note@-1:23 {{insert '->' and return type}}
} }
struct ExpansionRequirementTest<each T> {}
extension ExpansionRequirementTest where repeat each T == Int {} // expected-error {{same-element requirements are not yet supported}}