diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index 031eb93099241..f3dbd34317aea 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -217,6 +217,8 @@ ERROR(number_cant_start_decl_name,none, (StringRef)) ERROR(expected_identifier_after_case_comma, PointsToFirstBadToken, "expected identifier after comma in enum 'case' declaration", ()) +ERROR(generic_param_cant_be_used_in_enum_case_decl, PointsToFirstBadToken, + "generic signature cannot be declared in enum 'case'. did you mean to attach it to enum declaration?", ()) ERROR(let_cannot_be_computed_property,none, "'let' declarations cannot be computed properties", ()) ERROR(let_cannot_be_observing_property,none, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 28f7da278c162..510db5fcb0ffb 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -8969,6 +8969,32 @@ Parser::parseDeclEnumCase(ParseDeclOptions Flags, diagnose(CaseLoc, diag::expected_identifier_in_decl, "enum 'case'"); } } + + // See if there are generic params. + auto genericResults = maybeParseGenericParams() + .getPtrOrNull(); + auto enumDecl = dyn_cast(CurDeclContext); + if (genericResults && !genericResults->getParams().empty() && enumDecl) { + auto genericParamDecl = genericResults->getParams().front(); + + std::string fixStr; + llvm::raw_string_ostream OS(fixStr); + genericResults->print(OS); + + // Check if enum is already generic. + auto enumGenericParams = enumDecl->getGenericParams(); + if (enumGenericParams && !enumGenericParams->getParams().empty()) { + diagnose(genericParamDecl->getStartLoc(), diag::generic_param_cant_be_used_in_enum_case_decl) + .fixItRemove(genericResults->getSourceRange()) + .fixItReplace(enumGenericParams->getSourceRange(), fixStr); + } else { + SourceLoc insertLoc = enumDecl->getNameLoc() + .getAdvancedLoc(enumDecl->getName().getLength()); + diagnose(genericParamDecl->getStartLoc(), diag::generic_param_cant_be_used_in_enum_case_decl) + .fixItRemove(genericResults->getSourceRange()) + .fixItInsert(insertLoc, fixStr); + } + } // See if there's a following argument type. ParserResult ArgParams; diff --git a/test/decl/enum/enumtest.swift b/test/decl/enum/enumtest.swift index 9cd20c410568a..6dc080d265345 100644 --- a/test/decl/enum/enumtest.swift +++ b/test/decl/enum/enumtest.swift @@ -636,3 +636,29 @@ if case nil = foo1 {} // Okay if case .none? = foo1 {} // Okay if case nil = foo2 {} // Okay if case .none?? = foo2 {} // Okay + +enum EnumCaseWithGenericDeclaration { + // expected-error@+1 {{cannot find type 'T' in scope}} + case foo(T) // expected-error {{generic signature cannot be declared in enum 'case'. did you mean to attach it to enum declaration?}} {{11-14=}} {{-2:36-36=}} + // expected-error@+1 {{cannot find type 'T' in scope}} + case bar(param: T) // expected-error {{generic signature cannot be declared in enum 'case'. did you mean to attach it to enum declaration?}} {{11-14=}} {{-4:36-36=}} + case baz // expected-error {{generic signature cannot be declared in enum 'case'. did you mean to attach it to enum declaration?}} {{11-14=}} {{-5:36-36=}} + case one, two // expected-error {{generic signature cannot be declared in enum 'case'. did you mean to attach it to enum declaration?}} {{16-21=}} {{-6:36-36=}} + case three, four // expected-error {{generic signature cannot be declared in enum 'case'. did you mean to attach it to enum declaration?}} {{13-22=}} {{-7:36-36=}} + // expected-error@+1 {{cannot find type 'T' in scope}} + case five(param: T), six // expected-error {{generic signature cannot be declared in enum 'case'. did you mean to attach it to enum declaration?}} {{12-15=}} {{-9:36-36=}} + // expected-error@+2 {{generic signature cannot be declared in enum 'case'. did you mean to attach it to enum declaration?}} {{13-16=}} {{-12:36-36=}} + // expected-error@+1 {{generic signature cannot be declared in enum 'case'. did you mean to attach it to enum declaration?}} {{23-26=}} {{-12:36-36=}} + case seven, eight + case nine // OK +} + +enum EnumWithGenericDeclaration { + case foo // expected-error {{generic signature cannot be declared in enum 'case'. did you mean to attach it to enum declaration?}} {{11-14=}} {{-1:32-41=}} + // expected-error@+1 {{cannot find type 'Key' in scope}} + case bar(param: Key) // expected-error {{generic signature cannot be declared in enum 'case'. did you mean to attach it to enum declaration?}} {{11-16=}} {{-3:32-41=}} + // expected-error@+2 {{generic signature cannot be declared in enum 'case'. did you mean to attach it to enum declaration?}} {{11-14=}} {{-6:32-41=}} + // expected-error@+1 {{generic signature cannot be declared in enum 'case'. did you mean to attach it to enum declaration?}} {{19-22=}} {{-6:32-41=}} + case one, two + case nine // OK +} \ No newline at end of file