From 44d2350e5fcf007fe8c87375a5aaa4e34ee0fb5f Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 19 Aug 2020 12:08:17 -0700 Subject: [PATCH] Fix tuple name homogeneity check (#40118) --- src/compiler/checker.ts | 7 ++-- .../namedTupleMembersErrors.errors.txt | 34 +++++++++++++------ .../reference/namedTupleMembersErrors.js | 6 ++++ .../reference/namedTupleMembersErrors.symbols | 31 +++++++++++------ .../reference/namedTupleMembersErrors.types | 9 +++++ .../tuple/named/namedTupleMembersErrors.ts | 3 ++ 6 files changed, 63 insertions(+), 27 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 242e096ce4e52..ba30516b2039e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31080,13 +31080,10 @@ namespace ts { function checkTupleType(node: TupleTypeNode) { const elementTypes = node.elements; let seenOptionalElement = false; - let seenNamedElement = false; + const hasNamedElement = some(elementTypes, isNamedTupleMember); for (let i = 0; i < elementTypes.length; i++) { const e = elementTypes[i]; - if (e.kind === SyntaxKind.NamedTupleMember) { - seenNamedElement = true; - } - else if (seenNamedElement) { + if (e.kind !== SyntaxKind.NamedTupleMember && hasNamedElement) { grammarErrorOnNode(e, Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names); break; } diff --git a/tests/baselines/reference/namedTupleMembersErrors.errors.txt b/tests/baselines/reference/namedTupleMembersErrors.errors.txt index af37194d193c7..4f971f984a44a 100644 --- a/tests/baselines/reference/namedTupleMembersErrors.errors.txt +++ b/tests/baselines/reference/namedTupleMembersErrors.errors.txt @@ -1,28 +1,40 @@ tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(1,41): error TS5084: Tuple members must all have names or all not have names. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(3,32): error TS5084: Tuple members must all have names or all not have names. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(5,32): error TS5084: Tuple members must all have names or all not have names. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(7,29): error TS5086: A labeled tuple element is declared as optional with a question mark after the name and before the colon, rather than after the type. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(9,46): error TS5087: A labeled tuple element is declared as rest with a `...` before the name, rather than before the type. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(11,49): error TS5087: A labeled tuple element is declared as rest with a `...` before the name, rather than before the type. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(11,52): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(13,39): error TS5085: A tuple member cannot be both optional and rest. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(15,44): error TS2574: A rest element type must be an array type. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(17,13): error TS2456: Type alias 'RecusiveRestUnlabeled' circularly references itself. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(18,13): error TS2456: Type alias 'RecusiveRest' circularly references itself. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(2,25): error TS5084: Tuple members must all have names or all not have names. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(4,32): error TS5084: Tuple members must all have names or all not have names. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(5,22): error TS5084: Tuple members must all have names or all not have names. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(7,32): error TS5084: Tuple members must all have names or all not have names. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(8,22): error TS5084: Tuple members must all have names or all not have names. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(10,29): error TS5086: A labeled tuple element is declared as optional with a question mark after the name and before the colon, rather than after the type. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(12,46): error TS5087: A labeled tuple element is declared as rest with a `...` before the name, rather than before the type. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(14,49): error TS5087: A labeled tuple element is declared as rest with a `...` before the name, rather than before the type. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(14,52): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(16,39): error TS5085: A tuple member cannot be both optional and rest. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(18,44): error TS2574: A rest element type must be an array type. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(20,13): error TS2456: Type alias 'RecusiveRestUnlabeled' circularly references itself. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(21,13): error TS2456: Type alias 'RecusiveRest' circularly references itself. -==== tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts (11 errors) ==== +==== tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts (14 errors) ==== export type Segment1 = [length: number, number]; // partially named, disallowed ~~~~~~ !!! error TS5084: Tuple members must all have names or all not have names. + export type Segment2 = [number, size: number]; // partially named, disallowed + ~~~~~~ +!!! error TS5084: Tuple members must all have names or all not have names. export type List = [item: any, ...any]; // partially named, disallowed ~~~~~~ !!! error TS5084: Tuple members must all have names or all not have names. + export type List2 = [any, ...remainder: any]; // partially named, disallowed + ~~~ +!!! error TS5084: Tuple members must all have names or all not have names. export type Pair = [item: any, any?]; // partially named, disallowed ~~~~ !!! error TS5084: Tuple members must all have names or all not have names. + export type Pair2 = [any, last?: any]; // partially named, disallowed + ~~~ +!!! error TS5084: Tuple members must all have names or all not have names. export type Opt = [element: string?]; // question mark on element disallowed ~~~~~~~ diff --git a/tests/baselines/reference/namedTupleMembersErrors.js b/tests/baselines/reference/namedTupleMembersErrors.js index 5b277b3efe05c..a436e61cd0ca1 100644 --- a/tests/baselines/reference/namedTupleMembersErrors.js +++ b/tests/baselines/reference/namedTupleMembersErrors.js @@ -1,9 +1,12 @@ //// [namedTupleMembersErrors.ts] export type Segment1 = [length: number, number]; // partially named, disallowed +export type Segment2 = [number, size: number]; // partially named, disallowed export type List = [item: any, ...any]; // partially named, disallowed +export type List2 = [any, ...remainder: any]; // partially named, disallowed export type Pair = [item: any, any?]; // partially named, disallowed +export type Pair2 = [any, last?: any]; // partially named, disallowed export type Opt = [element: string?]; // question mark on element disallowed @@ -26,8 +29,11 @@ exports.__esModule = true; //// [namedTupleMembersErrors.d.ts] export declare type Segment1 = [length: number, number]; +export declare type Segment2 = [number, size: number]; export declare type List = [item: any, ...any]; +export declare type List2 = [any, ...remainder: any]; export declare type Pair = [item: any, any?]; +export declare type Pair2 = [any, last?: any]; export declare type Opt = [element: string?]; export declare type Trailing = [first: string, rest: ...string[]]; export declare type OptTrailing = [first: string, rest: ...?string[]]; diff --git a/tests/baselines/reference/namedTupleMembersErrors.symbols b/tests/baselines/reference/namedTupleMembersErrors.symbols index 613bf86cddd0e..6040512d2da27 100644 --- a/tests/baselines/reference/namedTupleMembersErrors.symbols +++ b/tests/baselines/reference/namedTupleMembersErrors.symbols @@ -2,32 +2,41 @@ export type Segment1 = [length: number, number]; // partially named, disallowed >Segment1 : Symbol(Segment1, Decl(namedTupleMembersErrors.ts, 0, 0)) +export type Segment2 = [number, size: number]; // partially named, disallowed +>Segment2 : Symbol(Segment2, Decl(namedTupleMembersErrors.ts, 0, 48)) + export type List = [item: any, ...any]; // partially named, disallowed ->List : Symbol(List, Decl(namedTupleMembersErrors.ts, 0, 48)) +>List : Symbol(List, Decl(namedTupleMembersErrors.ts, 1, 46)) + +export type List2 = [any, ...remainder: any]; // partially named, disallowed +>List2 : Symbol(List2, Decl(namedTupleMembersErrors.ts, 3, 39)) export type Pair = [item: any, any?]; // partially named, disallowed ->Pair : Symbol(Pair, Decl(namedTupleMembersErrors.ts, 2, 39)) +>Pair : Symbol(Pair, Decl(namedTupleMembersErrors.ts, 4, 45)) + +export type Pair2 = [any, last?: any]; // partially named, disallowed +>Pair2 : Symbol(Pair2, Decl(namedTupleMembersErrors.ts, 6, 37)) export type Opt = [element: string?]; // question mark on element disallowed ->Opt : Symbol(Opt, Decl(namedTupleMembersErrors.ts, 4, 37)) +>Opt : Symbol(Opt, Decl(namedTupleMembersErrors.ts, 7, 38)) export type Trailing = [first: string, rest: ...string[]]; // dots on element disallowed ->Trailing : Symbol(Trailing, Decl(namedTupleMembersErrors.ts, 6, 37)) +>Trailing : Symbol(Trailing, Decl(namedTupleMembersErrors.ts, 9, 37)) export type OptTrailing = [first: string, rest: ...string[]?]; // dots+question on element disallowed ->OptTrailing : Symbol(OptTrailing, Decl(namedTupleMembersErrors.ts, 8, 58)) +>OptTrailing : Symbol(OptTrailing, Decl(namedTupleMembersErrors.ts, 11, 58)) export type OptRest = [first: string, ...rest?: string[]]; // rest+optional disallowed ->OptRest : Symbol(OptRest, Decl(namedTupleMembersErrors.ts, 10, 62)) +>OptRest : Symbol(OptRest, Decl(namedTupleMembersErrors.ts, 13, 62)) export type NonArrayRest = [first: string, ...rest: number]; // non-arraylike rest, disallowed ->NonArrayRest : Symbol(NonArrayRest, Decl(namedTupleMembersErrors.ts, 12, 58)) +>NonArrayRest : Symbol(NonArrayRest, Decl(namedTupleMembersErrors.ts, 15, 58)) export type RecusiveRestUnlabeled = [string, ...RecusiveRestUnlabeled]; ->RecusiveRestUnlabeled : Symbol(RecusiveRestUnlabeled, Decl(namedTupleMembersErrors.ts, 14, 60)) ->RecusiveRestUnlabeled : Symbol(RecusiveRestUnlabeled, Decl(namedTupleMembersErrors.ts, 14, 60)) +>RecusiveRestUnlabeled : Symbol(RecusiveRestUnlabeled, Decl(namedTupleMembersErrors.ts, 17, 60)) +>RecusiveRestUnlabeled : Symbol(RecusiveRestUnlabeled, Decl(namedTupleMembersErrors.ts, 17, 60)) export type RecusiveRest = [first: string, ...rest: RecusiveRest]; // marked as incorrect, same as above ->RecusiveRest : Symbol(RecusiveRest, Decl(namedTupleMembersErrors.ts, 16, 71)) ->RecusiveRest : Symbol(RecusiveRest, Decl(namedTupleMembersErrors.ts, 16, 71)) +>RecusiveRest : Symbol(RecusiveRest, Decl(namedTupleMembersErrors.ts, 19, 71)) +>RecusiveRest : Symbol(RecusiveRest, Decl(namedTupleMembersErrors.ts, 19, 71)) diff --git a/tests/baselines/reference/namedTupleMembersErrors.types b/tests/baselines/reference/namedTupleMembersErrors.types index 761437dac55d7..0ae16d3b68353 100644 --- a/tests/baselines/reference/namedTupleMembersErrors.types +++ b/tests/baselines/reference/namedTupleMembersErrors.types @@ -2,12 +2,21 @@ export type Segment1 = [length: number, number]; // partially named, disallowed >Segment1 : Segment1 +export type Segment2 = [number, size: number]; // partially named, disallowed +>Segment2 : Segment2 + export type List = [item: any, ...any]; // partially named, disallowed >List : [any, ...any[]] +export type List2 = [any, ...remainder: any]; // partially named, disallowed +>List2 : [any, ...any[]] + export type Pair = [item: any, any?]; // partially named, disallowed >Pair : Pair +export type Pair2 = [any, last?: any]; // partially named, disallowed +>Pair2 : Pair2 + export type Opt = [element: string?]; // question mark on element disallowed >Opt : Opt diff --git a/tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts b/tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts index 75eb3d3deca24..6a1f5a0537085 100644 --- a/tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts +++ b/tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts @@ -1,10 +1,13 @@ // @declaration: true export type Segment1 = [length: number, number]; // partially named, disallowed +export type Segment2 = [number, size: number]; // partially named, disallowed export type List = [item: any, ...any]; // partially named, disallowed +export type List2 = [any, ...remainder: any]; // partially named, disallowed export type Pair = [item: any, any?]; // partially named, disallowed +export type Pair2 = [any, last?: any]; // partially named, disallowed export type Opt = [element: string?]; // question mark on element disallowed