Skip to content

Commit d602465

Browse files
committed
Parse: Allow an empty generic argument list, for variadic types
1 parent e7c2f9d commit d602465

File tree

3 files changed

+67
-32
lines changed

3 files changed

+67
-32
lines changed

include/swift/AST/TypeRepr.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,6 @@ class GenericIdentTypeRepr final : public ComponentIdentTypeRepr,
366366
: ComponentIdentTypeRepr(TypeReprKind::GenericIdent, Loc, Id),
367367
AngleBrackets(AngleBrackets) {
368368
Bits.GenericIdentTypeRepr.NumGenericArgs = GenericArgs.size();
369-
assert(!GenericArgs.empty());
370369
#ifndef NDEBUG
371370
for (auto arg : GenericArgs)
372371
assert(arg != nullptr);

lib/Parse/ParseType.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,9 @@ ParserStatus Parser::parseGenericArguments(SmallVectorImpl<TypeRepr *> &Args,
622622
assert(startsWithLess(Tok) && "Generic parameter list must start with '<'");
623623
LAngleLoc = consumeStartingLess();
624624

625-
{
625+
// Allow an empty generic parameter list, since this is meaningful with
626+
// variadic generic types.
627+
if (!startsWithGreater(Tok)) {
626628
while (true) {
627629
ParserResult<TypeRepr> Ty = parseType(diag::expected_type);
628630
if (Ty.isNull() || Ty.hasCodeCompletion()) {
@@ -699,19 +701,22 @@ Parser::parseTypeIdentifier(bool isParsingQualifiedDeclBaseType) {
699701
if (Loc.isValid()) {
700702
SourceLoc LAngle, RAngle;
701703
SmallVector<TypeRepr*, 8> GenericArgs;
704+
bool HasGenericArgs = false;
702705
if (startsWithLess(Tok)) {
706+
HasGenericArgs = true;
703707
auto genericArgsStatus = parseGenericArguments(GenericArgs, LAngle, RAngle);
704708
if (genericArgsStatus.isErrorOrHasCompletion())
705709
return genericArgsStatus;
706710
}
707711
EndLoc = Loc.getEndLoc();
708712

709713
ComponentIdentTypeRepr *CompT;
710-
if (!GenericArgs.empty())
714+
if (HasGenericArgs) {
711715
CompT = GenericIdentTypeRepr::create(Context, Loc, Name, GenericArgs,
712716
SourceRange(LAngle, RAngle));
713-
else
717+
} else {
714718
CompT = new (Context) SimpleIdentTypeRepr(Loc, Name);
719+
}
715720
ComponentsR.push_back(CompT);
716721
}
717722

test/Generics/variadic_generic_types.swift

Lines changed: 59 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,76 @@
22

33
// REQUIRES: asserts
44

5-
struct TupleStruct<First, Rest...> {
6-
var first: First
7-
var rest: (Rest...)
8-
}
9-
10-
func directAliases() {
11-
typealias Tuple<Ts...> = (Ts...)
5+
func bindAll() {
6+
struct Bind<U...> {}
127

13-
typealias Many<T, U, V, Ws...> = Tuple<T, U, V, Ws... >
14-
15-
let _: Many<Int, String, Double, Void, Void, Void, Void> = 42 // expected-error {{cannot convert value of type 'Int' to specified type}}
8+
typealias Zero = Bind< > // OK
9+
typealias One = Bind<Int> // OK
10+
typealias Two = Bind<Int, String> // OK
11+
typealias Three = Bind<Int, String, Float> // OK
1612
}
1713

1814
func bindPrefix() {
19-
struct Bind<Prefix, U...> {}
15+
struct Bind<Prefix, U...> {} // expected-note {{generic type 'Bind' declared here}}
2016

21-
typealias TooFew0 = Bind<> // expected-error {{expected type}}
22-
typealias TooFew1 = Bind<String> // OK
23-
typealias TooFew2 = Bind<String, String> // OK
24-
typealias JustRight = Bind<String, String, String> // OK
25-
typealias Oversaturated = Bind<String, String, String, String, String, String, String, String> // OK
17+
typealias Zero = Bind< > // expected-error {{generic type 'Bind' specialized with too few type parameters (got 0, but expected at least 1)}}
18+
typealias One = Bind<Int> // OK
19+
typealias Two = Bind<Int, String> // OK
20+
typealias Three = Bind<Int, String, Float> // OK
2621
}
2722

2823
func bindSuffix() {
29-
struct Bind<U..., Suffix> {}
24+
struct Bind<U..., Suffix> {} // expected-note {{generic type 'Bind' declared here}}
3025

31-
typealias TooFew0 = Bind<> // expected-error {{expected type}}
32-
typealias TooFew1 = Bind<String> // OK
33-
typealias TooFew2 = Bind<String, String> // OK
34-
typealias JustRight = Bind<String, String, String> // OK
35-
typealias Oversaturated = Bind<String, String, String, String, String, String, String, String> // OK
26+
typealias Zero = Bind< > // expected-error {{generic type 'Bind' specialized with too few type parameters (got 0, but expected at least 1)}}
27+
typealias One = Bind<Int> // OK
28+
typealias Two = Bind<Int, String> // OK
29+
typealias Three = Bind<Int, String, Float> // OK
3630
}
3731

3832
func bindPrefixAndSuffix() {
39-
struct Bind<Prefix, U..., Suffix> {} // expected-note {{generic type 'Bind' declared here}}
33+
struct Bind<Prefix, U..., Suffix> {} // expected-note 2{{generic type 'Bind' declared here}}
34+
35+
typealias Zero = Bind< > // expected-error {{generic type 'Bind' specialized with too few type parameters (got 0, but expected at least 2)}}
36+
typealias One = Bind<Int> // expected-error {{generic type 'Bind' specialized with too few type parameters (got 1, but expected at least 2)}}
37+
typealias Two = Bind<Int, String> // OK
38+
typealias Three = Bind<Int, String, Float> // OK
39+
typealias Four = Bind<Int, String, Float, Bool> // OK
40+
}
41+
42+
func bindAliasAll() {
43+
typealias Bind<U...> = (U...)
44+
45+
typealias Zero = Bind< > // OK
46+
typealias One = Bind<Int> // OK
47+
typealias Two = Bind<Int, String> // OK
48+
typealias Three = Bind<Int, String, Float> // OK
49+
}
50+
51+
func bindAliasPrefix() {
52+
typealias Bind<Prefix, U...> = (Prefix, U...) // expected-note {{generic type 'Bind' declared here}}
4053

41-
typealias TooFew0 = Bind<> // expected-error {{expected type}}
42-
typealias TooFew1 = Bind<String> // expected-error {{generic type 'Bind' specialized with too few type parameters (got 1, but expected at least 2)}}
43-
typealias TooFew2 = Bind<String, String> // OK
44-
typealias JustRight = Bind<String, String, String> // OK
45-
typealias Oversaturated = Bind<String, String, String, String, String, String, String, String> // OK
54+
typealias Zero = Bind< > // expected-error {{generic type 'Bind' specialized with too few type parameters (got 0, but expected at least 1)}}
55+
typealias One = Bind<Int> // OK
56+
typealias Two = Bind<Int, String> // OK
57+
typealias Three = Bind<Int, String, Float> // OK
4658
}
59+
60+
func bindAliasSuffix() {
61+
typealias Bind<U..., Suffix> = (U..., Suffix) // expected-note {{generic type 'Bind' declared here}}
62+
63+
typealias Zero = Bind< > // expected-error {{generic type 'Bind' specialized with too few type parameters (got 0, but expected at least 1)}}
64+
typealias One = Bind<Int> // OK
65+
typealias Two = Bind<Int, String> // OK
66+
typealias Three = Bind<Int, String, Float> // OK
67+
}
68+
69+
func bindAliasPrefixAndSuffix() {
70+
typealias Bind<Prefix, U..., Suffix> = (Prefix, U..., Suffix) // expected-note 2{{generic type 'Bind' declared here}}
71+
72+
typealias Zero = Bind< > // expected-error {{generic type 'Bind' specialized with too few type parameters (got 0, but expected at least 2)}}
73+
typealias One = Bind<Int> // expected-error {{generic type 'Bind' specialized with too few type parameters (got 1, but expected at least 2)}}
74+
typealias Two = Bind<Int, String> // OK
75+
typealias Three = Bind<Int, String, Float> // OK
76+
typealias Four = Bind<Int, String, Float, Bool> // OK
77+
}

0 commit comments

Comments
 (0)