@@ -7963,14 +7963,125 @@ ParserResult<ClassDecl> Parser::parseDeclClass(ParseDeclOptions Flags,
79637963 return DCC.fixupParserResult (Status, CD);
79647964}
79657965
7966+ ParserStatus Parser::parsePrimaryAssociatedTypes (
7967+ SmallVectorImpl<AssociatedTypeDecl *> &AssocTypes) {
7968+ SourceLoc LAngleLoc = consumeStartingLess ();
7969+
7970+ ParserStatus Result;
7971+ SyntaxParsingContext PATContext (SyntaxContext,
7972+ SyntaxKind::PrimaryAssociatedTypeList);
7973+
7974+ bool HasNextParam = false ;
7975+ do {
7976+ SyntaxParsingContext ATContext (SyntaxContext,
7977+ SyntaxKind::PrimaryAssociatedType);
7978+
7979+ // Note that we're parsing a declaration.
7980+ StructureMarkerRAII ParsingDecl (*this , Tok.getLoc (),
7981+ StructureMarkerKind::Declaration);
7982+
7983+ // Parse attributes.
7984+ DeclAttributes Attrs;
7985+ if (Tok.hasComment ())
7986+ Attrs.add (new (Context) RawDocCommentAttr (Tok.getCommentRange ()));
7987+ parseDeclAttributeList (Attrs);
7988+
7989+ // Parse the name of the parameter.
7990+ Identifier Name;
7991+ SourceLoc NameLoc;
7992+ if (parseIdentifier (Name, NameLoc, /* diagnoseDollarPrefix=*/ true ,
7993+ diag::expected_primary_associated_type_name)) {
7994+ Result.setIsParseError ();
7995+ break ;
7996+ }
7997+
7998+ // Parse the ':' followed by a type.
7999+ SmallVector<InheritedEntry, 1 > Inherited;
8000+ if (Tok.is (tok::colon)) {
8001+ (void )consumeToken ();
8002+ ParserResult<TypeRepr> Ty;
8003+
8004+ if (Tok.isAny (tok::identifier, tok::code_complete, tok::kw_protocol,
8005+ tok::kw_Any)) {
8006+ Ty = parseType ();
8007+ } else if (Tok.is (tok::kw_class)) {
8008+ diagnose (Tok, diag::unexpected_class_constraint);
8009+ diagnose (Tok, diag::suggest_anyobject)
8010+ .fixItReplace (Tok.getLoc (), " AnyObject" );
8011+ consumeToken ();
8012+ Result.setIsParseError ();
8013+ } else {
8014+ diagnose (Tok, diag::expected_generics_type_restriction, Name);
8015+ Result.setIsParseError ();
8016+ }
8017+
8018+ if (Ty.hasCodeCompletion ())
8019+ return makeParserCodeCompletionStatus ();
8020+
8021+ if (Ty.isNonNull ())
8022+ Inherited.push_back ({Ty.get ()});
8023+ }
8024+
8025+ ParserResult<TypeRepr> UnderlyingTy;
8026+ if (Tok.is (tok::equal)) {
8027+ SyntaxParsingContext InitContext (SyntaxContext,
8028+ SyntaxKind::TypeInitializerClause);
8029+ consumeToken (tok::equal);
8030+ UnderlyingTy = parseType (diag::expected_type_in_associatedtype);
8031+ Result |= UnderlyingTy;
8032+ if (UnderlyingTy.isNull ())
8033+ return Result;
8034+ }
8035+
8036+ auto *AssocType = new (Context)
8037+ AssociatedTypeDecl (CurDeclContext, NameLoc, Name, NameLoc,
8038+ UnderlyingTy.getPtrOrNull (),
8039+ /* trailingWhere=*/ nullptr );
8040+ AssocType->getAttrs () = Attrs;
8041+ if (!Inherited.empty ())
8042+ AssocType->setInherited (Context.AllocateCopy (Inherited));
8043+ AssocType->getAttrs ().add (new (Context) PrimaryAssociatedTypeAttr (
8044+ /* Implicit=*/ true ));
8045+
8046+ AssocTypes.push_back (AssocType);
8047+
8048+ // Parse the comma, if the list continues.
8049+ HasNextParam = consumeIf (tok::comma);
8050+ } while (HasNextParam);
8051+
8052+ // Parse the closing '>'.
8053+ SourceLoc RAngleLoc;
8054+ if (startsWithGreater (Tok)) {
8055+ RAngleLoc = consumeStartingGreater ();
8056+ } else {
8057+ diagnose (Tok, diag::expected_rangle_primary_associated_type_list);
8058+ diagnose (LAngleLoc, diag::opening_angle);
8059+
8060+ // Skip until we hit the '>'.
8061+ RAngleLoc = skipUntilGreaterInTypeList ();
8062+ }
8063+
8064+ return Result;
8065+ }
8066+
79668067// / Parse a 'protocol' declaration, doing no token skipping on error.
79678068// /
79688069// / \verbatim
79698070// / decl-protocol:
79708071// / protocol-head '{' protocol-member* '}'
79718072// /
79728073// / protocol-head:
7973- // / 'protocol' attribute-list identifier inheritance?
8074+ // / attribute-list 'protocol' identifier primary-associated-type-list?
8075+ // / inheritance?
8076+ // /
8077+ // / primary-associated-type-list:
8078+ // / '<' primary-associated-type+ '>'
8079+ // /
8080+ // / primary-associated-type:
8081+ // / identifier inheritance? default-associated-type
8082+ // /
8083+ // / default-associated-type:
8084+ // / '=' type
79748085// /
79758086// / protocol-member:
79768087// / decl-func
@@ -7991,12 +8102,20 @@ parseDeclProtocol(ParseDeclOptions Flags, DeclAttributes &Attributes) {
79918102 if (Status.isErrorOrHasCompletion ())
79928103 return Status;
79938104
7994- // Protocols don't support generic parameters, but people often want them and
7995- // we want to have good error recovery if they try them out. Parse them and
7996- // produce a specific diagnostic if present.
7997- if (startsWithLess (Tok)) {
7998- diagnose (Tok, diag::generic_arguments_protocol);
7999- maybeParseGenericParams ();
8105+ SmallVector<AssociatedTypeDecl *, 2 > PrimaryAssociatedTypes;
8106+
8107+ if (Context.LangOpts .EnableParameterizedProtocolTypes ) {
8108+ if (startsWithLess (Tok)) {
8109+ Status |= parsePrimaryAssociatedTypes (PrimaryAssociatedTypes);
8110+ }
8111+ } else {
8112+ // Protocols don't support generic parameters, but people often want them and
8113+ // we want to have good error recovery if they try them out. Parse them and
8114+ // produce a specific diagnostic if present.
8115+ if (startsWithLess (Tok)) {
8116+ diagnose (Tok, diag::generic_arguments_protocol);
8117+ maybeParseGenericParams ();
8118+ }
80008119 }
80018120
80028121 DebuggerContextChange DCC (*this );
@@ -8035,6 +8154,12 @@ parseDeclProtocol(ParseDeclOptions Flags, DeclAttributes &Attributes) {
80358154
80368155 ContextChange CC (*this , Proto);
80378156
8157+ // Re-parent the primary associated type declarations into the protocol.
8158+ for (auto *AssocType : PrimaryAssociatedTypes) {
8159+ AssocType->setDeclContext (Proto);
8160+ Proto->addMember (AssocType);
8161+ }
8162+
80388163 // Parse the body.
80398164 {
80408165 SyntaxParsingContext BlockContext (SyntaxContext, SyntaxKind::MemberDeclBlock);
0 commit comments