Skip to content

Variadic generic diagnostics [5.9] #65769

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
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
8 changes: 7 additions & 1 deletion include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -5398,6 +5398,12 @@ ERROR(vararg_not_allowed,none,
ERROR(experimental_type_with_parameter_pack,none,
"generic types with parameter packs are experimental",
())
ERROR(more_than_one_pack_in_type,none,
"generic type cannot declare more than one type pack", ())
ERROR(enum_with_pack,none,
"enums cannot declare a type pack", ())
ERROR(superclass_with_pack,none,
"cannot inherit from a generic class that declares a type pack", ())
ERROR(expansion_not_allowed,none,
"pack expansion %0 can only appear in a function parameter list, "
"tuple element, or generic argument list", (Type))
Expand All @@ -5419,7 +5425,7 @@ ERROR(pack_reference_must_be_in_expansion,none,
"pack reference %0 requires expansion using keyword 'repeat'",
(TypeRepr*))
ERROR(pack_type_requires_keyword_each,none,
"pack type %0 must be referenced with 'each'",
"type pack %0 must be referenced with 'each'",
(TypeRepr*))
ERROR(tuple_duplicate_label,none,
"cannot create a tuple with a duplicate element label", ())
Expand Down
41 changes: 37 additions & 4 deletions lib/Sema/TypeCheckDeclPrimary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,14 +471,24 @@ static void checkGenericParams(GenericContext *ownerCtx) {
if (!genericParams)
return;

auto *decl = ownerCtx->getAsDecl();
bool isGenericType = isa<GenericTypeDecl>(decl);
bool hasPack = false;

for (auto gp : *genericParams) {
// Diagnose generic types with a parameter packs if VariadicGenerics
// is not enabled.
auto *decl = ownerCtx->getAsDecl();
auto &ctx = decl->getASTContext();
if (gp->isParameterPack() && isa<GenericTypeDecl>(decl) &&
!ctx.LangOpts.hasFeature(Feature::VariadicGenerics)) {
decl->diagnose(diag::experimental_type_with_parameter_pack);
if (gp->isParameterPack() && isGenericType) {
if (!ctx.LangOpts.hasFeature(Feature::VariadicGenerics)) {
decl->diagnose(diag::experimental_type_with_parameter_pack);
}

if (hasPack) {
gp->diagnose(diag::more_than_one_pack_in_type);
}

hasPack = true;
}

TypeChecker::checkDeclAttributes(gp);
Expand Down Expand Up @@ -2545,6 +2555,17 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
void visitEnumDecl(EnumDecl *ED) {
checkUnsupportedNestedType(ED);

// Temporary restriction until we figure out pattern matching and
// enum case construction with packs.
if (auto genericSig = ED->getGenericSignature()) {
for (auto paramTy : genericSig.getGenericParams()) {
if (paramTy->isParameterPack()) {
ED->diagnose(diag::enum_with_pack);
break;
}
}
}

// FIXME: Remove this once we clean up the mess involving raw values.
(void) ED->getInterfaceType();

Expand Down Expand Up @@ -2824,6 +2845,18 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
else if (superclass->isActor())
CD->diagnose(diag::actor_inheritance,
/*distributed=*/CD->isDistributedActor());

// Enforce a temporary restriction on inheriting from a superclass
// type with a pack, until we figure out the semantics of method
// overrides in these situations.
if (auto genericSig = superclass->getGenericSignature()) {
for (auto paramTy : genericSig.getGenericParams()) {
if (paramTy->isParameterPack()) {
CD->diagnose(diag::superclass_with_pack);
break;
}
}
}
}

if (CD->isDistributedActor()) {
Expand Down
10 changes: 5 additions & 5 deletions test/Constraints/pack-expansion-expressions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,28 +103,28 @@ func returnEachPackReference<each T>(_ t: repeat each T) -> each T { // expected
fatalError()
}

// expected-error@+1 {{pack type 'T' must be referenced with 'each'}}{{63-63=each }}
// expected-error@+1 {{type pack 'T' must be referenced with 'each'}}{{63-63=each }}
func returnRepeatTuple<each T>(_ t: repeat each T) -> (repeat T) {
fatalError()
}

// expected-error@+2 {{pack reference 'T' requires expansion using keyword 'repeat'}}
// expected-error@+1 {{pack type 'T' must be referenced with 'each'}}{{55-55=each }}
// expected-error@+1 {{type pack 'T' must be referenced with 'each'}}{{55-55=each }}
func parameterAsPackTypeWithoutExpansion<each T>(_ t: T) {
}

// expected-error@+2 {{pack reference 'T' requires expansion using keyword 'repeat'}}
// expected-error@+1 {{pack type 'T' must be referenced with 'each'}}{{57-57=each }}
// expected-error@+1 {{type pack 'T' must be referenced with 'each'}}{{57-57=each }}
func returnPackReference<each T>(_ t: repeat each T) -> T {
fatalError()
}

func packTypeParameterOutsidePackExpansionType<each T>(_ t: T,
// expected-error@-1 {{pack reference 'T' requires expansion using keyword 'repeat'}}
// expected-error@-2 {{pack type 'T' must be referenced with 'each'}}{{61-61=each }}
// expected-error@-2 {{type pack 'T' must be referenced with 'each'}}{{61-61=each }}
_ a: Array<T>) {
// expected-error@-1 {{pack reference 'T' requires expansion using keyword 'repeat'}}
// expected-error@-2 {{pack type 'T' must be referenced with 'each'}}{{67-67=each }}
// expected-error@-2 {{type pack 'T' must be referenced with 'each'}}{{67-67=each }}
}

func expansionOfNonPackType<T>(_ t: repeat each T) {}
Expand Down
24 changes: 24 additions & 0 deletions test/Generics/variadic_generic_types.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
// RUN: %target-typecheck-verify-swift -enable-experimental-feature VariadicGenerics

// Because of -enable-experimental-feature VariadicGenerics
// REQUIRES: asserts

// Disallowed cases
struct MultiplePack<each T, each U> {} // expected-error {{generic type cannot declare more than one type pack}}
typealias MultiplePackAlias<each T, each U> = (repeat each T, repeat each U) // expected-error {{generic type cannot declare more than one type pack}}

// Temporary limitations
enum EnumWithPack<each T> { // expected-error {{enums cannot declare a type pack}}
case cheddar
}

class ClassWithPack<each T> {}

struct OuterStruct<each T> {
enum NestedEnum { // expected-error {{enums cannot declare a type pack}}
case smokedGouda
}

class NestedClass {}
}

class BadInheritance1: ClassWithPack<Int> {} // expected-error {{cannot inherit from a generic class that declares a type pack}}
class BadInheritance2: OuterStruct<Int>.NestedClass {} // expected-error {{cannot inherit from a generic class that declares a type pack}}

// Type resolution of variadic type aliases
func bindAll() {
struct Bind<each U> {}

Expand Down
2 changes: 1 addition & 1 deletion test/type/pack_expansion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func f5<each T>() -> () -> (repeat each T) {}

func f6<each T>() -> (repeat each T) -> () {}

enum E<each T> {
enum E<each T> { // expected-error {{enums cannot declare a type pack}}
case f1(_: repeat each T)

case f2(_: G<repeat each T>)
Expand Down