Skip to content

[SE-0393] Require the repeat keyword for generic requirement expansions. #65134

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -5387,9 +5387,8 @@ ERROR(invalid_expansion_argument,none,
ERROR(expansion_not_variadic,none,
"pack expansion %0 must contain at least one pack reference", (Type))
ERROR(pack_reference_outside_expansion,none,
"pack reference %0 can only appear in pack expansion "
"%select{or generic requirement|}1",
(Type, /*inExpression*/ bool))
"pack reference %0 can only appear in pack expansion ",
(Type))
ERROR(each_non_pack,none,
"'each' cannot be applied to non-pack type %0",
(Type))
Expand Down
32 changes: 24 additions & 8 deletions include/swift/AST/GenericParamList.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class RequirementRepr {
SourceLoc SeparatorLoc;
RequirementReprKind Kind : 2;
bool Invalid : 1;
bool IsExpansionPattern : 1;
TypeRepr *FirstType;

/// The second element represents the right-hand side of the constraint.
Expand All @@ -72,13 +73,17 @@ class RequirementRepr {
StringRef AsWrittenString;

RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind,
TypeRepr *FirstType, TypeRepr *SecondType)
TypeRepr *FirstType, TypeRepr *SecondType,
bool IsExpansionPattern)
: SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
IsExpansionPattern(IsExpansionPattern),
FirstType(FirstType), SecondType(SecondType) { }

RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind,
TypeRepr *FirstType, LayoutConstraintLoc SecondLayout)
TypeRepr *FirstType, LayoutConstraintLoc SecondLayout,
bool IsExpansionPattern)
: SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
IsExpansionPattern(IsExpansionPattern),
FirstType(FirstType), SecondLayout(SecondLayout) { }

public:
Expand All @@ -92,8 +97,10 @@ class RequirementRepr {
/// subject must conform, or superclass from which the subject must inherit.
static RequirementRepr getTypeConstraint(TypeRepr *Subject,
SourceLoc ColonLoc,
TypeRepr *Constraint) {
return { ColonLoc, RequirementReprKind::TypeConstraint, Subject, Constraint };
TypeRepr *Constraint,
bool IsExpansionPattern) {
return { ColonLoc, RequirementReprKind::TypeConstraint, Subject, Constraint,
IsExpansionPattern };
}

/// Construct a new same-type requirement.
Expand All @@ -104,8 +111,10 @@ class RequirementRepr {
/// \param SecondType The second type.
static RequirementRepr getSameType(TypeRepr *FirstType,
SourceLoc EqualLoc,
TypeRepr *SecondType) {
return { EqualLoc, RequirementReprKind::SameType, FirstType, SecondType };
TypeRepr *SecondType,
bool IsExpansionPattern) {
return { EqualLoc, RequirementReprKind::SameType, FirstType, SecondType,
IsExpansionPattern };
}

/// Construct a new layout-constraint requirement.
Expand All @@ -118,9 +127,10 @@ class RequirementRepr {
/// subject must conform.
static RequirementRepr getLayoutConstraint(TypeRepr *Subject,
SourceLoc ColonLoc,
LayoutConstraintLoc Layout) {
LayoutConstraintLoc Layout,
bool IsExpansionPattern) {
return {ColonLoc, RequirementReprKind::LayoutConstraint, Subject,
Layout};
Layout, IsExpansionPattern};
}

/// Determine the kind of requirement
Expand All @@ -129,6 +139,12 @@ class RequirementRepr {
/// Determine whether this requirement is invalid.
bool isInvalid() const { return Invalid; }

/// Whether this requirement repr is the pattern of a requirement
/// expansion, e.g. `repeat G<each T> == (each U).A`
bool isExpansionPattern() const {
return IsExpansionPattern;
}

/// Mark this requirement invalid.
void setInvalid() { Invalid = true; }

Expand Down
7 changes: 7 additions & 0 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1842,16 +1842,23 @@ void PrintAST::printRequirement(const Requirement &req) {
Printer << ")) : Any";
return;
case RequirementKind::Layout:
if (req.getFirstType()->hasParameterPack())
Printer << "repeat ";
printTransformedType(req.getFirstType());
Printer << " : ";
req.getLayoutConstraint()->print(Printer, Options);
return;
case RequirementKind::Conformance:
case RequirementKind::Superclass:
if (req.getFirstType()->hasParameterPack())
Printer << "repeat ";
printTransformedType(req.getFirstType());
Printer << " : ";
break;
case RequirementKind::SameType:
if (req.getFirstType()->hasParameterPack() ||
req.getSecondType()->hasParameterPack())
Printer << "repeat ";
printTransformedType(req.getFirstType());
Printer << " == ";
break;
Expand Down
4 changes: 2 additions & 2 deletions lib/AST/CASTBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,12 +559,12 @@ void *GenericParamList_create(void *ctx, void *lAngleLoc,
case BridgedRequirementReprKindTypeConstraint:
requirements.push_back(RequirementRepr::getTypeConstraint(
(TypeRepr *)req.FirstType, getSourceLocFromPointer(req.SeparatorLoc),
(TypeRepr *)req.SecondType));
(TypeRepr *)req.SecondType, /*isExpansionPattern*/false));
break;
case BridgedRequirementReprKindSameType:
requirements.push_back(RequirementRepr::getSameType(
(TypeRepr *)req.FirstType, getSourceLocFromPointer(req.SeparatorLoc),
(TypeRepr *)req.SecondType));
(TypeRepr *)req.SecondType, /*isExpansionPattern*/false));
break;
case BridgedRequirementReprKindLayoutConstraint:
llvm_unreachable("cannot handle layout constraints!");
Expand Down
21 changes: 16 additions & 5 deletions lib/Parse/ParseGeneric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,13 @@ ParserStatus Parser::parseGenericWhereClause(
break;
}

// Parse the 'repeat' keyword for requirement expansions.
bool isRequirementExpansion = false;
if (Tok.is(tok::kw_repeat)) {
consumeToken();
isRequirementExpansion = true;
}

// 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<TypeRepr> FirstType = parseType();
Expand Down Expand Up @@ -326,7 +333,8 @@ ParserStatus Parser::parseGenericWhereClause(
// Add the layout requirement.
Requirements.push_back(RequirementRepr::getLayoutConstraint(
FirstType.get(), ColonLoc,
LayoutConstraintLoc(Layout, LayoutLoc)));
LayoutConstraintLoc(Layout, LayoutLoc),
isRequirementExpansion));
}
} else {
// Parse the protocol or composition.
Expand All @@ -337,7 +345,7 @@ ParserStatus Parser::parseGenericWhereClause(

// Add the requirement.
Requirements.push_back(RequirementRepr::getTypeConstraint(
FirstType.get(), ColonLoc, Protocol.get()));
FirstType.get(), ColonLoc, Protocol.get(), isRequirementExpansion));
}
} else if ((Tok.isAnyOperator() && Tok.getText() == "==") ||
Tok.is(tok::equal)) {
Expand Down Expand Up @@ -367,15 +375,18 @@ ParserStatus Parser::parseGenericWhereClause(
// completion token in the TypeRepr.
Requirements.push_back(RequirementRepr::getTypeConstraint(
FirstType.get(), EqualLoc,
new (Context) ErrorTypeRepr(SecondType.get()->getLoc())));
new (Context) ErrorTypeRepr(SecondType.get()->getLoc()),
isRequirementExpansion));
} else {
Requirements.push_back(RequirementRepr::getSameType(
FirstType.get(), EqualLoc, SecondType.get()));
FirstType.get(), EqualLoc, SecondType.get(),
isRequirementExpansion));
}
} else if (FirstType.hasCodeCompletion()) {
// Recover by adding dummy constraint.
Requirements.push_back(RequirementRepr::getTypeConstraint(
FirstType.get(), PreviousLoc, new (Context) ErrorTypeRepr(PreviousLoc)));
FirstType.get(), PreviousLoc, new (Context) ErrorTypeRepr(PreviousLoc),
isRequirementExpansion));
} else {
diagnose(Tok, diag::expected_requirement_delim);
Status.setIsParseError();
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/CSDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6043,7 +6043,7 @@ bool InvalidPackElement::diagnoseAsError() {

bool InvalidPackReference::diagnoseAsError() {
emitDiagnostic(diag::pack_reference_outside_expansion,
packType, /*inExpression*/true);
packType);
return true;
}

Expand Down
3 changes: 2 additions & 1 deletion lib/Sema/TypeCheckGeneric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1028,7 +1028,8 @@ RequirementRequest::evaluate(Evaluator &evaluator,
context = TypeResolverContext::GenericRequirement;
}
auto options = TypeResolutionOptions(context);
options |= TypeResolutionFlags::AllowPackReferences;
if (reqRepr.isExpansionPattern())
options |= TypeResolutionFlags::AllowPackReferences;
if (owner.dc->isInSpecializeExtensionContext())
options |= TypeResolutionFlags::AllowUsableFromInline;
Optional<TypeResolution> resolution;
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/TypeCheckType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4637,7 +4637,7 @@ NeverNullType TypeResolver::resolvePackElement(PackElementTypeRepr *repr,
if (!options.contains(TypeResolutionFlags::AllowPackReferences)) {
ctx.Diags.diagnose(repr->getLoc(),
diag::pack_reference_outside_expansion,
packReference, /*inExpression*/false);
packReference);
return ErrorType::get(ctx);
}

Expand Down
8 changes: 4 additions & 4 deletions test/Constraints/pack-expansion-expressions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ protocol P {
func f(_ self: Self) -> Self
}

func outerArchetype<each T, U>(t: repeat each T, u: U) where each T: P {
func outerArchetype<each T, U>(t: repeat each T, u: U) where repeat each T: P {
let _: (repeat (each T.A, U)) = (repeat ((each t).value, u))
}

func sameElement<each T, U>(t: repeat each T, u: U) where each T: P, each T == U {
func sameElement<each T, U>(t: repeat each T, u: U) where repeat each T: P, repeat each T == U {
// expected-error@-1{{same-element requirements are not yet supported}}

// FIXME: Opened element archetypes in diagnostics
Expand All @@ -65,15 +65,15 @@ func sameElement<each T, U>(t: repeat each T, u: U) where each T: P, each T == U
}

func forEachEach<each C, U>(c: repeat each C, function: (U) -> Void)
where each C: Collection, each C.Element == U {
where repeat each C: Collection, repeat (each C).Element == U {
// expected-error@-1{{same-element requirements are not yet supported}}

// FIXME: Opened element archetypes in diagnostics
_ = (repeat (each c).forEach(function))
// expected-error@-1 {{cannot convert value of type '(U) -> Void' to expected argument type '(τ_1_0.Element) throws -> Void'}}
}

func typeReprPacks<each T>(_ t: repeat each T) where each T: ExpressibleByIntegerLiteral {
func typeReprPacks<each T: ExpressibleByIntegerLiteral>(_ t: repeat each T) {
_ = (repeat Array<each T>())
_ = (repeat 1 as each T)

Expand Down
5 changes: 3 additions & 2 deletions test/Constraints/pack_expansion_types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,8 @@ func patternInstantiationConcreteInvalid() {
let _: (Array<Int>, Set<String>) = patternInstantiationTupleTest1() // expected-error {{type of expression is ambiguous without more context}}
}

func patternInstantiationGenericValid<each T, each U>(t: repeat each T, u: repeat each U) where (repeat (each T, each U)): Any, each T: Hashable {
func patternInstantiationGenericValid<each T, each U>(t: repeat each T, u: repeat each U)
where (repeat (each T, each U)): Any, repeat each T: Hashable {
let _: (repeat Array<each T>) = patternInstantiationTupleTest1()
let _: (repeat Array<each T>, Array<String>) = patternInstantiationTupleTest1()
let _: (Array<String>, repeat Array<each T>) = patternInstantiationTupleTest1()
Expand All @@ -286,7 +287,7 @@ func patternInstantiationGenericValid<each T, each U>(t: repeat each T, u: repea
let _: (Dictionary<Int, String>, repeat Dictionary<each T, each U>, Dictionary<Double, Character>) -> () = patternInstantiationFunctionTest2()
}

func patternInstantiationGenericInvalid<each T>(t: repeat each T) where each T: Hashable {
func patternInstantiationGenericInvalid<each T: Hashable>(t: repeat each T) {
let _: (repeat Set<each T>) = patternInstantiationTupleTest1() // expected-error {{cannot convert value of type '(repeat Array<each T>)' to specified type '(repeat Set<each T>)}}
// expected-error@-1 {{generic parameter 'T' could not be inferred}}

Expand Down
8 changes: 5 additions & 3 deletions test/Constraints/variadic_generic_constraints.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ takesAnyObject(C(), S(), C()) // expected-error {{type of expression is ambiguo

// Same-type requirements

func takesParallelSequences<each T, each U>(t: repeat each T, u: repeat each U) where each T: Sequence, each U: Sequence, each T.Element == each U.Element {}
// expected-note@-1 {{where 'T.Element' = 'String', 'U.Element' = 'Int'}}

// expected-note@+1 {{where 'T.Element' = 'String', 'U.Element' = 'Int'}}
func takesParallelSequences<each T, each U>(t: repeat each T, u: repeat each U)
where repeat each T: Sequence,
repeat each U: Sequence,
repeat (each T).Element == (each U).Element {}
takesParallelSequences() // ok
takesParallelSequences(t: Array<Int>(), u: Set<Int>()) // ok
takesParallelSequences(t: Array<String>(), Set<Int>(), u: Set<String>(), Array<Int>()) // ok
Expand Down
4 changes: 2 additions & 2 deletions test/Constraints/variadic_generic_functions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
// REQUIRES: asserts

func debugPrint<each T>(_ items: repeat each T)
where each T: CustomDebugStringConvertible
where repeat each T: CustomDebugStringConvertible
{
/*for (item: T) in items {
stdout.write(item.debugDescription)
}*/
}

func max<each T>(_ values: repeat each T) -> (repeat each T)?
where each T: Comparable
where repeat each T: Comparable
{
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion test/Frontend/experimental_feature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ let x = BOOM

// Use variadic generics
func debugPrint<each T>(_ items: repeat each T)
where each T: CustomDebugStringConvertible
where repeat each T: CustomDebugStringConvertible
{
}
14 changes: 7 additions & 7 deletions test/Generics/pack-shape-requirements.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ func inferSameShape<each T, each U>(ts t: repeat each T, us u: repeat each U) wh
}

// CHECK-LABEL: desugarSameShape(ts:us:)
// CHECK-NEXT: Generic signature: <each T, each U where T : P, (repeat (each T, each U)) : Any, U : P>
func desugarSameShape<each T, each U>(ts t: repeat each T, us u: repeat each U) where each T: P, each U: P, (repeat (each T.A, each U.A)): Any {
}
// CHECK-NEXT: Generic signature: <each T, each U where repeat T : P, (repeat (each T, each U)) : Any, repeat U : P>
func desugarSameShape<each T, each U>(ts t: repeat each T, us u: repeat each U)
where repeat each T: P, repeat each U: P, (repeat (each T.A, each U.A)): Any {}

// CHECK-LABEL: multipleSameShape1(ts:us:vs:)
// CHECK-NEXT: Generic signature: <each T, each U, each V where (repeat (each T, each U)) : Any, (repeat (each U, each V)) : Any>
Expand Down Expand Up @@ -49,14 +49,14 @@ func multipleSameShape6<each T, each U, each V>(ts t: repeat each T, us u: repea
struct Ts<each T> {
struct Us<each U> {
// CHECK-LABEL: Ts.Us.packEquality()
// CHECK-NEXT: Generic signature: <each T, each U where T == U>
func packEquality() where each T == each U, (repeat (each T, each U)): Any {
// CHECK-NEXT: Generic signature: <each T, each U where repeat T == U>
func packEquality() where repeat each T == each U, (repeat (each T, each U)): Any {
}

struct Vs<each V> {
// CHECK-LABEL: Ts.Us.Vs.packEquality()
// CHECK-NEXT: Generic signature: <each T, each U, each V where T == U, (repeat (each T, each V)) : Any>
func packEquality() where each T == each U, (repeat (each U, each V)): Any {
// CHECK-NEXT: Generic signature: <each T, each U, each V where repeat T == U, (repeat (each T, each V)) : Any>
func packEquality() where repeat each T == each U, (repeat (each U, each V)): Any {
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/Generics/tuple-conformances.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ protocol P {
func f()
}

extension Builtin.TheTupleType: P where each Elements: P {
extension Builtin.TheTupleType: P where repeat each Elements: P {
typealias A = (repeat each Elements.A)
typealias B = Float
func f() {}
Expand Down
4 changes: 2 additions & 2 deletions test/Generics/variadic_generic_requirements.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ _ = Layout<Class, Subclass>.self // ok
_ = Layout<Int, String>.self // expected-error {{'Layout' requires that 'Int' be a class type}}

struct Outer<each T: Sequence> {
struct Inner<each U: Sequence> where each T.Element == each U.Element {}
struct Inner<each U: Sequence> where repeat each T.Element == each U.Element {}
// expected-note@-1 {{requirement specified as 'T.Element' == 'U.Element' [with each T = Array<Int>, Array<String>; each U = Set<String>, Set<Int>]}}
// expected-note@-2 {{requirement specified as 'T.Element' == 'U.Element' [with each T = Array<Int>; each U = Set<Int>, Set<String>]}}

Expand All @@ -36,4 +36,4 @@ _ = Outer<Array<Int>, Array<String>>.Inner<Set<String>, Set<Int>>.self // expec
_ = Outer<Array<Int>>.Inner<Set<Int>, Set<String>>.self // expected-error {{'Outer<Array<Int>>.Inner' requires the types 'Pack{Int}' and 'Pack{Int, String}' be equivalent}}

_ = Outer<Array<Int>, Array<String>>.InnerShape<Set<String>, Set<Int>>.self // ok
_ = Outer<Array<Int>>.InnerShape<Set<Int>, Set<String>>.self // expected-error {{'Outer<Array<Int>>.InnerShape' requires the type packs 'Pack{Array<Int>}' and 'Pack{Set<Int>, Set<String>}' have the same shape}}
_ = Outer<Array<Int>>.InnerShape<Set<Int>, Set<String>>.self // expected-error {{'Outer<Array<Int>>.InnerShape' requires the type packs 'Pack{Array<Int>}' and 'Pack{Set<Int>, Set<String>}' have the same shape}}
6 changes: 3 additions & 3 deletions test/IRGen/run_variadic_generics.sil
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ entry(%intIndex : $Builtin.Word):
return %t : $()
}

sil @unwrap_from_PA : $<each T_1 : PA where each T_1.A : P> (Builtin.Word) -> () {
sil @unwrap_from_PA : $<each T_1 : PA where repeat each T_1.A : P> (Builtin.Word) -> () {
entry(%intIndex : $Builtin.Word):
%direct_access_from_parameter_with_conformance = function_ref @direct_access_from_parameter_with_conformance : $@convention(thin) <each T_1: P> (Builtin.Word) -> ()
apply %direct_access_from_parameter_with_conformance<Pack{repeat GenFwdP<each T_1.A>}>(%intIndex) : $@convention(thin) <each T_1: P> (Builtin.Word) -> ()
Expand All @@ -637,7 +637,7 @@ entry(%intIndex : $Builtin.Word):
sil @extract_associatedtype_with_conformance : $<each T_1 : P> (Builtin.Word) -> () {
entry(%intIndex : $Builtin.Word):
%innerIndex = dynamic_pack_index %intIndex of $Pack{repeat each T_1}
%token = open_pack_element %innerIndex of <each U_1 : PA where each U_1.A : P> at <Pack{repeat GenAssocPA<GenFwdP<each T_1>>}>, shape $U_1, uuid "01234567-89AB-CDEF-0123-000000000005"
%token = open_pack_element %innerIndex of <each U_1 : PA where repeat each U_1.A : P> at <Pack{repeat GenAssocPA<GenFwdP<each T_1>>}>, shape $U_1, uuid "01234567-89AB-CDEF-0123-000000000005"
%metatype_1 = metatype $@thick (@pack_element("01234567-89AB-CDEF-0123-000000000005") U_1).Type
%printGenericType = function_ref @printGenericType : $@convention(thin) <T> (@thick T.Type) -> ()
apply %printGenericType<(@pack_element("01234567-89AB-CDEF-0123-000000000005") U_1)>(%metatype_1) : $@convention(thin) <T> (@thick T.Type) -> ()
Expand All @@ -653,7 +653,7 @@ sil @extract_associatedtype_with_conformance2 : $<each T_1 : P, Tee : P, each T_
entry(%intIndex : $Builtin.Word):
%innerIndex = dynamic_pack_index %intIndex of $Pack{repeat GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<each T_1>>>>, repeat GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<each T_1>>>>}
%token = open_pack_element %innerIndex
of <each U_1 : PA, Ewe : PA, each U_2 : PA where each U_1.A : PA, each U_1.A.A : PA, each U_1.A.A.A : P, Ewe.A : PA, Ewe.A.A : PA, Ewe.A.A.A : P, each U_2.A : PA, each U_2.A.A : PA, each U_2.A.A.A : P, (repeat (each U_1, each U_2)): Any>
of <each U_1 : PA, Ewe : PA, each U_2 : PA where repeat each U_1.A : PA, repeat each U_1.A.A : PA, repeat each U_1.A.A.A : P, Ewe.A : PA, Ewe.A.A : PA, Ewe.A.A.A : P, repeat each U_2.A : PA, repeat each U_2.A.A : PA, repeat each U_2.A.A.A : P, (repeat (each U_1, each U_2)): Any>
at <
Pack{repeat GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<each T_1>>>>, repeat GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<each T_1>>>>},
GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<Tee>>>>,
Expand Down
2 changes: 1 addition & 1 deletion test/IRGen/variadic_generic_captures.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,6 @@ public func has_witness_table_pack<each T: Sequence>(t: repeat each T) -> () ->
}

public func has_witness_table_pack2<each T: Sequence>(t: repeat each T) -> () -> ()
where each T.Element: Sequence {
where repeat each T.Element: Sequence {
return { _ = (repeat (each T).Element.Element).self }
}
Loading