GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Variadic tuple types by ahejlsberg · Pull Request #39094 · microsoft/TypeScript

Conversation

@ahejlsberg

@ahejlsberg Anders Hejlsberg (ahejlsberg) commented Jun 16, 2020 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

This PR implements variadic tuple types, i.e. the ability for tuple types to have spreads of generic types that can be replaced with actual elements through type instantiation. The PR effectively implements the features discussed in #5453.

Some examples of new capabilities provided in this PR:

// Variadic tuple elements

type Foo<T extends unknown[]> = [string, ...T, number];

type T1 = Foo<[boolean]>;  // [string, boolean, number]
type T2 = Foo<[number, number]>;  // [string, number, number, number]
type T3 = Foo<[]>;  // [string, number]

// Strongly typed tuple concatenation

function concat<T extends unknown[], U extends unknown[]>(t: [...T], u: [...U]): [...T, ...U] {
    return [...t, ...u];
}

const ns = [0, 1, 2, 3];  // number[]

const t1 = concat([1, 2], ['hello']);  // [number, number, string]
const t2 = concat([true], t1);  // [boolean, number, number, string]
const t3 = concat([true], ns);  // [boolean, ...number[]]

// Inferring parts of tuple types

declare function foo<T extends string[], U>(...args: [...T, () => void]): T;

foo(() => {});  // []
foo('hello', 'world', () => {});  // ["hello", "world"]
foo('hello', 42, () => {});  // Error, number not assignable to string

// Inferring to a composite tuple type

function curry<T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) {
    return (...b: U) => f(...a, ...b);
}

const fn1 = (a: number, b: string, c: boolean, d: string[]) => 0;

const c0 = curry(fn1);  // (a: number, b: string, c: boolean, d: string[]) => number
const c1 = curry(fn1, 1);  // (b: string, c: boolean, d: string[]) => number
const c2 = curry(fn1, 1, 'abc');  // (c: boolean, d: string[]) => number
const c3 = curry(fn1, 1, 'abc', true);  // (d: string[]) => number
const c4 = curry(fn1, 1, 'abc', true, ['x', 'y']);  // () => number

Structure and instantiation

The basic structure of a non-generic tuple type remains unchanged with this PR: Zero or more required elements, followed by zero or more optional elements, optionally followed by a rest element (for example [A, B?, ...C[]]). However, it is now possible to have variadic elements anywhere in a tuple type, except following the optional rest element (for example [A, ...T, B?, ...U, ...C[]]).

A variadic elemement is a spread element of the form ...T, where T is a generic type constrained to any array or tuple type (specifically, any type that is assignable to readonly any[]). Intuitively, a variadic element ...T is a placeholder that is replaced with one or more elements through generic type instantiation. Instantiation of a tuple type with a variadic element ...T depends on the type argument provided for T as follows:

  • When the type argument for T is a union type, the union is spread over the tuple type. For example, [A, ...T, B] instantiated with X | Y | Z as the type argument for T yields a union of instantiations of [A, ...T, B] with X, Y and Z as the type argument for T respectively.
  • When the type argument is a tuple type, T is replaced with the elements of that tuple type. For example, [A, ...T, B] instantiated with [X, Y] as the type argument for T yields [A, X, Y, B].
  • When the type argument is an array type, T is replaced with a rest element. For example, [A, ...T] instantiated with X[] as the type argument for T yields [A, ...X[]].
  • When the type argument is another generic type, T is simply replaced with that type.
  • When the type argument is any, T is replaced with ...any[].
  • When the type argument is never, the entire result is never.

Instantiation of a generic tuple type includes normalization to ensure the resulting tuple type follows the basic structure described above. Specifically:

  • Optionality is removed from any optional elements that precede a required element. For example, [A?, ...T, B?] instantiated with [X, Y?] as the type argument for T yields [A, X, Y?, B?].
  • Rest elements absorb any following elements. For example, [A, ...T, B] instantiated with X[] as the type argument for T yields [A, ...(X | B)[]].
  • Tuples with only a single rest element are reduced to array types. For example, [...X[]] is reduced to simply X[].

NOTE: With #41544 we now support starting and middle rest elements in tuple types.

Type relationships

Generally, a tuple type S is related to a tuple type T by pairwise relating elements of S to the elements of T. Variadic elements are processed as follows:

  • A variadic element ...U in S is related to a variadic element ...V in T if U is related to V.
  • A variadic element ...U in S is related to a rest element ...X[] in T if U is related to X[].

Some examples:

function foo1<T extends unknown[], U extends T>(x: [string, ...unknown[]], y: [string, ...T], z: [string, ...U]) {
    x = y;  // Ok
    x = z;  // Ok
    y = x;  // Error
    y = z;  // Ok
    z = x;  // Error
    z = y;  // Error
}

Tuple types with single variadic elements have the following relations:

  • [...T] is related to T.
  • T is related to readonly [...T].
  • T is related to [...T] when T is constrained to a mutable array or tuple type.

Some examples:

function foo2<T extends readonly unknown[]>(t: T, m: [...T], r: readonly [...T]) {
    t = m;  // Ok
    t = r;  // Error
    m = t;  // Error
    m = r;  // Error
    r = t;  // Ok
    r = m;  // Ok
}

Type inference

Inference between tuple types with the same structure (i.e. same number of elements and fixed, variadic, or rest kind matched to the same kind in each position), simply infers pairwise between the element types. For example, inference from [string, ...Partial<S>, number?] to [string, ...T, number?] infers Partial<S> for T.

Inference between tuple types S and T with different structure divides each tuple into a starting fixed part, a middle part, and an ending fixed part. Any one of these parts may be empty.

  • The starting fixed parts of S and T consist of those elements in S and T that are fixed (i.e. neither variadic nor rest elements) in both types matching from the start of each type.

  • If T contains at least one variadic element and S has no ending rest element, the ending fixed parts of S and T consist of those elements in S and T that are fixed in both types matching from the end of each type.

  • If T contains at least one variadic element and S has an ending rest element, the ending fixed part of T consists of those elements in T that are fixed matching from the end of the type, and the ending fixed part of S is empty.

  • If T contains no variadic elements, the ending fixed parts of S and T are empty.

  • The middle parts of S and T are those elements in S and T that remain between the starting and ending fixed parts of the types respectively.

Inference then proceeds as follows:

  • Pairwise infer between the elements in the starting parts.

  • If the middle part of S is a single rest element, infer from that rest element to every element in the middle part of T.

  • If the middle part of T is a single variadic or rest element, infer from a tuple consisting of the middle part of S to that variadic or rest element.

  • If the middle part of T is exactly two variadic elements ...A and ...B, and an implied arity exists for A, infer from a tuple consisting of the initial middle part of S to A and from a tuple consisting of the remaining middle part of S to B, where the length of the initial middle part corresponds to the implied arity for A.

  • Pairwise infer between the elements in the ending parts, or infer from the rest element in S to the elements of the ending part of T.

In the context of inference for a call of a generic function with a rest parameter R, the implied arity for R is the number of rest arguments supplied for R. In all other contexts, a type parameter has no implied arity. For an example of inference involving an implied arity, see the curry function in the introduction.

Some examples:

type First<T extends readonly unknown[]> = T[0];
type DropFirst<T extends readonly unknown[]> = T extends readonly [any?, ...infer U] ? U : [...T];
type Last<T extends readonly unknown[]> =
    T extends readonly [...infer _, infer U] ? U :
    T extends readonly [...infer _, (infer U)?] ? U | undefined :
    undefined;
type DropLast<T extends readonly unknown[]> = T extends readonly [...infer U, any?] ? U : [...T];

type T1 = First<[number, boolean, string]>;  // [number]
type T2 = DropFirst<[number, boolean, string]>;  // [boolean, string]
type T3 = Last<[number, boolean, string]>;  // [string]
type T4 = DropLast<[number, boolean, string]>;  // [number, boolean]

Spreads in array literals

When an array literal has a tuple type, a spread of a value of a generic array-like type produces a variadic element. For example:

function foo3<T extends unknown[], U extends unknown[]>(t: [...T], u: [...U]) {
    return [1, ...t, 2, ...u, 3] as const;  // readonly [1, ...T, 2, ...U, 3]
}

const t = foo3(['hello'], [10, true]);  // readonly [1, string, 2, number, boolean, 3]

When the contextual type of an array literal is a tuple type, a tuple type is inferred for the array literal. The type [...T], where T is an array-like type parameter, can conveniently be used to indicate a preference for inference of tuple types:

declare function ft1<T extends unknown[]>(t: T): T;
declare function ft2<T extends unknown[]>(t: T): readonly [...T];
declare function ft3<T extends unknown[]>(t: [...T]): T;
declare function ft4<T extends unknown[]>(t: [...T]): readonly [...T];

ft1(['hello', 42]);  // (string | number)[]
ft2(['hello', 42]);  // readonly (string | number)[]
ft3(['hello', 42]);  // [string, number]
ft4(['hello', 42]);  // readonly [string, number]

Indexing and destructuring

Indexing and destructuring of generic tuple types appropriately recognizes fixed elements at the start of the tuple type. Beyond the fixed elements, the type is simply a union of the remaining element types.

function f1<T extends unknown[]>(t: [string, ...T], n: number) {
    const a = t[0];  // string
    const b = t[1];  // [string, ...T][1]
    const c = t[2];  // [string, ...T][2]
    const d = t[n];  // [string, ...T][number]
}

function f2<T extends unknown[]>(t: [string, ...T, number], n: number) {
    const a = t[0];  // string
    const b = t[1];  // [string, ...T, number][1]
    const c = t[2];  // [string, ...T, number][2]
    const d = t[n];  // [string, ...T, number][number]
}

function f3<T extends unknown[]>(t: [string, ...T]) {
    let [...ax] = t;  // [string, ...T]
    let [b1, ...bx] = t;  // string, [...T]
    let [c1, c2, ...cx] = t;  // string, [string, ...T][1], T[number][]
}

function f4<T extends unknown[]>(t: [string, ...T, number]) {
    let [...ax] = t;  // [string, ...T, number]
    let [b1, ...bx] = t;  // string, [...T, number]
    let [c1, c2, ...cx] = t;  // string, [string, ...T, number][1], (number | T[number])[]
}

Rest parameters and spread arguments

Spread expressions with fixed length tuples are now appropriately flattened in argument lists. For example:

declare function fs1(a: number, b: string, c: boolean, ...d: number[]): void;

function fs2(t1: [number, string], t2: [boolean], a1: number[]) {
    fs1(1, 'abc', true, 42, 43, 44);
    fs1(...t1, true, 42, 43, 44);
    fs1(...t1, ...t2, 42, 43, 44);
    fs1(...t1, ...t2, ...a1);
    fs1(...t1);  // Error: Expected at least 3 arguments, but got 2
    fs1(...t1, 45);  // Error: Type '45' is not assignable to type 'boolean'
}

A rest parameter of a generic tuple type can be used to infer types from the middle part of argument lists. For example:

declare function fr1<T extends unknown[]>(x: number, ...args: [...T, number]): T;

function fr2<U extends unknown[]>(u: U) {
    fr1(1, 2);  // []
    fr1(1, 'hello', true, 2);  // [string, boolean]
    fr1(1, ...u, 'hi', 2);  // [...U, string]
    fr1(1);  // Error: Expected 2 arguments, but got 1
}

Application of mapped types

When a mapped type is applied to a generic tuple type, non-variadic elements are eagerly mapped but variadic elements continue to be generic. Effectively, M<[A, B?, ...T, ...C[]] is resolved as [...M<[A]>, ...M<[B?]>, ...M<T>, ...M<C[]>]. For example:

type TP1<T extends unknown[]> = Partial<[string, ...T, number]>;  // [string?, ...Partial<T>, number?]

Fixes #5453.
Fixes #26113.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

matijagrcic, kitos, jayphelps, jasonkuhrt, justinbayctxs, robertt, alex-okrushko, aminpaks, IllusionMH, JirkaVebr, and 229 more reacted with thumbs up emoji rowdyrotifer, AwesomeObserver, macabeus, j-oliveras, harrysolovay, Quelklef, raveclassic, fuafa, btoo, millsp, and 19 more reacted with laugh emoji RemyRylan, RyanCavanaugh, paul-sachs, zen0wu, ssnielsen, ddprrt, robertt, alexrock, guywaldman, dderevjanik, and 116 more reacted with hooray emoji orta, matijagrcic, mrmlnc, kitos, jasonkuhrt, alex-okrushko, dpraimeyuu, cartant, JirkaVebr, AwesomeObserver, and 114 more reacted with heart emoji robertt, matijagrcic, dderevjanik, kitos, antonvasin, jasonkuhrt, alex-okrushko, mohsen1, hipstersmoothie, JoshuaKGoldberg, and 58 more reacted with rocket emoji brainkim, jasonkuhrt, alex-okrushko, macabeus, j-oliveras, CYBAI, Quelklef, raveclassic, fuafa, sod, and 11 more reacted with eyes emoji
All reactions
  • 👍 239 reactions
  • 😄 29 reactions
  • 🎉 126 reactions
  • ❤️ 124 reactions
  • 🚀 68 reactions
  • 👀 21 reactions
Anders Hejlsberg (ahejlsberg) added 26 commits June 1, 2020 14:11
@ahejlsberg
Initial implementation of variadic tuple types
7410ac9
@ahejlsberg
Accept new baselines
e5d6be7
@ahejlsberg
Handle variadic elements in tuple type inference
6d6bf6d
@ahejlsberg
Special case inference between tuples with matching structure
5679f36
@ahejlsberg
Restore check that rest element is last element
94dd625
@ahejlsberg
Handle variadic tuples in relationship checking
8669342
@ahejlsberg
Accept new baselines
34fd780
@ahejlsberg
Infer readonly constraints when inferring from readonly tuples
e8466d7
@ahejlsberg
Fix lint issues
20eb59e
@ahejlsberg
T assignable to readonly [...T] and [...T] assignable to T
54d7d40
@ahejlsberg
Consistent tuple normalization
d2b3128
@ahejlsberg
Create variadic tuple types from array literal expressions
5902c21
@ahejlsberg
Accept new baselines
5d78ed1
@ahejlsberg
Array literals have tuple types when contextual type is readonly
b6b9d4a
@ahejlsberg
Accept new baselines
0a7c6a9
@ahejlsberg
Optional elements before required elements become required elements
97184ab
@ahejlsberg
Update logic for rest parameters and spread arguments
7449a6b
@ahejlsberg
Revert special case of contextual readonly array type
7f0917b
@ahejlsberg
Accept new baselines
0388e8e
@ahejlsberg
Fix lint issue
635d440
@ahejlsberg
Switch entirely to createTupleType based on element flags
32bbd4c
@ahejlsberg
Don't infer readonly tuple types when inferring to variadic elements
10a9eb9
@ahejlsberg
Handle mapped types applied to generic tuple types
bb989fc
@ahejlsberg
Handle constraint of indexed access type with generic tuple type
fec03a1
@ahejlsberg
Merge branch 'master' into variadicTuples
9a04edc
# Conflicts:
#	src/compiler/checker.ts
#	tests/baselines/reference/callWithSpread3.errors.txt
#	tests/baselines/reference/genericRestParameters1.errors.txt
#	tests/baselines/reference/ramdaToolsNoInfinite.types
@ahejlsberg
Accept new baselines
01d3b54
@ahejlsberg Anders Hejlsberg (ahejlsberg) mentioned this pull request Jun 16, 2020
Proposal: Variadic Kinds -- Give specific types to variadic functions #5453
Closed
@ahejlsberg
Anders Hejlsberg (ahejlsberg) requested review from Daniel Rosenwasser (DanielRosenwasser), Ryan Cavanaugh (RyanCavanaugh) and Nathan Shively-Sanders (sandersn) June 16, 2020 20:09
@JoshuaKGoldberg Josh Ghoulberg 👻 (JoshuaKGoldberg) mentioned this pull request Aug 13, 2020
Type error emitted for valid type index lookups in variadic tuple types #40030
Closed
@jdmichaud

jdmichaud commented Aug 13, 2020

Copy link
Copy Markdown

Will the type of Promise.all be improved thanks to this?

tonivj5, samhh, and Damvilion reacted with eyes emoji
All reactions
  • 👀 3 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@w0rp

Andrew Wray (w0rp) commented Aug 13, 2020

Copy link
Copy Markdown

Will the type of Promise.all be improved thanks to this?

That's a very good example of something that can easily be improved by using this. Maybe someone should raise an issue or create a pull request for it.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@IllusionMH

Andrii Dieiev (IllusionMH) commented Aug 13, 2020

Copy link
Copy Markdown
Contributor

It's already discussed in #39788

jdmichaud reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@voliva Victor Oliva (voliva) mentioned this pull request Aug 16, 2020
feat(bind): factory with nested keys re-rxjs/react-rxjs#78
Merged
@jdmichaud jdmichaud mentioned this pull request Aug 19, 2020
Update downlevel-dts for tuple enhancements in 4.0 #39099
Closed
@patricklx Patrick Pircher (patricklx) mentioned this pull request Aug 20, 2020
[Bluebird] support then -> static .all -> then DefinitelyTyped/DefinitelyTyped#46720
Closed
@millsp pierre (millsp) mentioned this pull request Aug 23, 2020
Support for TypeScript 4.0 millsp/ts-toolbelt#140
Closed
@AllanZhengYP AllanZhengYP mentioned this pull request Oct 12, 2020
[util-dynamodb]: use recursive conditional type to support better type inferrence. aws/aws-sdk-js-v3#1564
Closed
@chocolateboy chocolateboy mentioned this pull request Nov 14, 2020
Allow inferring rest element types in conditional types involving tuples #25719
Open
4 tasks done
@ahejlsberg

Anders Hejlsberg (ahejlsberg) commented Nov 16, 2020

Copy link
Copy Markdown
Member Author

With #41544 we now support rest elements in starting and middle positions of tuple types. This addresses some of the issues that were discussed in this PR, such as #39094 (comment).

dead-claudia, joakim, millsp, and falkenhawk reacted with hooray emoji
All reactions
  • 🎉 4 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@typescript-bot TypeScript Bot (typescript-bot) assigned Anders Hejlsberg (ahejlsberg) Nov 16, 2020
@typescript-bot TypeScript Bot (typescript-bot) added the Author: Team label Nov 16, 2020
Facebook Community Bot (facebook-github-bot) pushed a commit to meta/pyre-check that referenced this pull request Feb 20, 2021
@pradeep90 @facebook-github-bot
Split and match ordered types by elements of known length.
e68b3a0
Summary:
Problem: To solve `Tuple[int, str, bool, bool] <: Tuple[int, *Ts, int]`, we need to solve `[int, str, bool, bool] <: [int, *Ts, int]`.

We do that by removing matching elements of known length from both the prefix and the suffix.

In the above example, `int` is in both prefixes, so we extract it. Next, the left side has `str`, which has a known fixed length 1, but the right side has `*Ts`, which doesn't have a known length. So, we don't extract that. Likewise, we can extract the matching suffix of `[bool] vs [int]` since they have known lengths. (We just split by lengths here, without checking for compatibility. That happens in `solve`.)

So, after splitting, we get

```
[int] - [str, bool] - [bool]
[int] - [   *Ts   ] - [int]
```

We solve each part pairwise. We check `int <: int`, `[str, bool] <: [*Ts]`, and `bool <: int`.

So, we end up solving it as `Ts = Tuple[str, bool]`.

There are other cases like unbounded tuples, bound vs free variables, multiple `*Ts`, and so on, but this is the core idea.

This is what TypeScript [does](microsoft/TypeScript#39094) for its variadic tuples. Note that we don't yet support unpacking unbounded tuples or concatenation of multiple variadics (that's in a future PEP).

Reviewed By: grievejia

Differential Revision: D26520882

fbshipit-source-id: 0df0d74becf3ee2a85caf3819093ccc336a5029d
This was referenced Apr 28, 2021
[v7] watch method return types when over 10 keys watched react-hook-form/react-hook-form#4994
Closed
Typing for watch & getValues react-hook-form/react-hook-form#5005
Merged
@tom-sherman Tom Sherman (tom-sherman) mentioned this pull request Jul 4, 2021
Support partial application on func tom-sherman/diddly#3
Draft
@brxck Brock McElroy (brxck) mentioned this pull request Jul 5, 2021
Refactor transformations and add name transformation cursorless-dev/cursorless#56
Merged
@mbullington Michael Bullington (mbullington) mentioned this pull request Jul 16, 2021
Improve Typescript definition for Map immutable-js/immutable-js#1841
Merged
Liu Bowen (lbwa) added a commit to lbwa/esw that referenced this pull request Jul 18, 2021
@lbwa
feat: use tuple as arg value type
6b999d5
see microsoft/TypeScript#39094 (comment)
@Alexsey Aleksey Bobyr (Alexsey) mentioned this pull request May 4, 2022
20 - Promise.all type-challenges/type-challenges#211
Open
@leaft leafyy (leaft) mentioned this pull request May 5, 2022
20 - Promise.all type-challenges/type-challenges#9289
Open
@astak16 柚子uccs (astak16) mentioned this pull request Jun 25, 2022
23. PromiseAll astak16/blog-ts-challenges#32
Open
@github-actions github-actions Bot mentioned this pull request Oct 4, 2022
[Korean] Fix weird expressions like '_제네릭_' microsoft/TypeScript-Website-Localizations#171
Merged
@guevara goddog (guevara) mentioned this pull request Dec 27, 2022
Effective TypeScript All I Want for Christmas Is These Seven TypeScript Improvements guevara/read-it-later#9162
Open
@jakebailey Jake Bailey (jakebailey) mentioned this pull request Jul 9, 2023
Tuple with element after spread not assignable to tuple with rest elements #33573
Closed
@AndreGeng Andre (AndreGeng) mentioned this pull request Sep 26, 2024
20 - Promise.all type-challenges/type-challenges#3273
Open
@ZiyaoWei Ziyao Wei (ZiyaoWei) mentioned this pull request Nov 8, 2024
Validator generator should type cast input/output types nanofuzz/nanofuzz#164
Closed
@olegdunkan olegdunkan mentioned this pull request Oct 8, 2025
Two consecutive variadic elements in the middle part of tuple type can't be recognized #62561
Open
@microsoft Microsoft (microsoft) locked as resolved and limited conversation to collaborators Oct 21, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Reviewers

@sandersn Nathan Shively-Sanders (sandersn) sandersn left review comments
@weswigham Wesley Wigham (weswigham) weswigham left review comments
@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) RyanCavanaugh left review comments
@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) DanielRosenwasser approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@ahejlsberg Anders Hejlsberg (ahejlsberg)

Labels

Author: Team For Milestone Bug PRs that fix a bug with a specific milestone

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Rest elements in generic tuple Proposal: Variadic Kinds -- Give specific types to variadic functions

Uh oh!

There was an error while loading. Please reload this page.

20 participants

@ahejlsberg @Artazor @RyanCavanaugh @typescript-bot @aminpaks @DanielRosenwasser @IllusionMH @ddprrt @jwbay @AlexAegis @HerringtonDarkholme @amitport @TylorS @sandersn @dead-claudia @millsp @treybrisbane @uhyo @bbrzoska @filipesabella
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.