@@ -2553,10 +2553,21 @@ tyconNameAndTyparDecls:
25532553 | opt_access path postfixTyparDecls
25542554 { Some $3, true, $1, Some(SynType.LongIdent($2)) }
25552555
2556- /* Type extension with general type: type (int * int) with ..., type struct (int * int) with ..., type int[] with ..., etc.
2556+ /* Non-struct tuple type extension: type (int * int) with ...
2557+ Uses explicit STAR to disambiguate from prefix typar decls ('a,'b) which use COMMA.
25572558 Validation of which types are valid for extension is deferred to CheckDeclarations.fs */
2558- | opt_access atomType
2559- { None, false, $1, Some $2 }
2559+ | opt_access LPAREN appTypeCanBeNullable STAR tupleOrQuotTypeElements rparen
2560+ { let mStar = rhs parseState 4
2561+ let path = SynTupleTypeSegment.Type $3 :: SynTupleTypeSegment.Star mStar :: $5
2562+ let mTuple = rhs2 parseState 2 6
2563+ None, false, $1, Some (SynType.Paren(SynType.Tuple(false, path, mTuple), mTuple)) }
2564+
2565+ /* Struct tuple type extension: type struct (int * int) with ... */
2566+ | opt_access STRUCT LPAREN appTypeCanBeNullable STAR tupleOrQuotTypeElements rparen
2567+ { let mStar = rhs parseState 5
2568+ let path = SynTupleTypeSegment.Type $4 :: SynTupleTypeSegment.Star mStar :: $6
2569+ let mTuple = rhs2 parseState 1 7
2570+ None, false, $1, Some (SynType.Tuple(true, path, mTuple)) }
25602571
25612572 /* Recovery: type ('T1 *) or type ('T1 *) with ... - trailing star, missing second type */
25622573 | opt_access LPAREN appTypeCanBeNullable STAR rparen
@@ -2593,10 +2604,20 @@ typarDeclList:
25932604 | typarDecl { [$1] }
25942605
25952606typarDecl:
2596- | opt_attributes typar
2607+ /* Split into attributed/non-attributed alternatives to avoid an epsilon-reduction of opt_attributes
2608+ that creates a shift/reduce conflict with appTypeCon in tyconNameAndTyparDecls tuple type rules. */
2609+ | typar
2610+ { SynTyparDecl([], $1, [], SynTyparDeclTrivia.Zero) }
2611+
2612+ | attributes typar
25972613 { SynTyparDecl($1, $2, [], SynTyparDeclTrivia.Zero) }
25982614
2599- | opt_attributes typar AMP intersectionConstraints
2615+ | typar AMP intersectionConstraints
2616+ { parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.ConstraintIntersectionOnFlexibleTypes (rhs2 parseState 2 3)
2617+ let constraints, mAmpersands = $3
2618+ SynTyparDecl([], $1, List.rev constraints, { AmpersandRanges = rhs parseState 2 :: List.rev mAmpersands }) }
2619+
2620+ | attributes typar AMP intersectionConstraints
26002621 { parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.ConstraintIntersectionOnFlexibleTypes (rhs2 parseState 3 4)
26012622 let constraints, mAmpersands = $4
26022623 SynTyparDecl($1, $2, List.rev constraints, { AmpersandRanges = rhs parseState 3 :: List.rev mAmpersands }) }
0 commit comments