From b5fc59435e286e87fe744660e43223f4b3ee6605 Mon Sep 17 00:00:00 2001 From: Matt McCutchen Date: Sun, 2 Sep 2018 14:59:00 -0400 Subject: [PATCH] For consistency, don't make inferences for unused type parameters when comparing two references to the same generic type. We want this even when strictFunctionTypes is off. Variance computation was previously disabled when strictFunctionTypes is off, but I removed that check without breaking any tests. Fixes #26815. --- src/compiler/checker.ts | 9 +++----- .../complexRecursiveCollections.types | 2 +- .../reference/independentTypeParameter.js | 12 ++++++++++ .../independentTypeParameter.symbols | 23 +++++++++++++++++++ .../reference/independentTypeParameter.types | 18 +++++++++++++++ .../compiler/independentTypeParameter.ts | 5 ++++ tests/cases/fourslash/genericCombinators3.ts | 2 ++ .../fourslash/staticGenericOverloads1.ts | 1 + 8 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/independentTypeParameter.js create mode 100644 tests/baselines/reference/independentTypeParameter.symbols create mode 100644 tests/baselines/reference/independentTypeParameter.types create mode 100644 tests/cases/compiler/independentTypeParameter.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index da1af15dfa458..299aeb41115de 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12298,12 +12298,9 @@ namespace ts { // a digest of the type comparisons that occur for each type argument when instantiations of the // generic type are structurally compared. We infer the variance information by comparing // instantiations of the generic type for type arguments with known relations. The function - // returns the emptyArray singleton if we're not in strictFunctionTypes mode or if the function - // has been invoked recursively for the given generic type. + // returns the emptyArray singleton if the function has been invoked recursively for the given + // generic type. function getVariances(type: GenericType): Variance[] { - if (!strictFunctionTypes) { - return emptyArray; - } const typeParameters = type.typeParameters || emptyArray; let variances = type.variances; if (!variances) { @@ -13379,7 +13376,7 @@ namespace ts { if (i < variances.length && variances[i] === Variance.Contravariant) { inferFromContravariantTypes(sourceTypes[i], targetTypes[i]); } - else { + else if (!(i < variances.length && variances[i] === Variance.Independent)) { inferFromTypes(sourceTypes[i], targetTypes[i]); } } diff --git a/tests/baselines/reference/complexRecursiveCollections.types b/tests/baselines/reference/complexRecursiveCollections.types index a9fc13e7d1dc1..feaff62048628 100644 --- a/tests/baselines/reference/complexRecursiveCollections.types +++ b/tests/baselines/reference/complexRecursiveCollections.types @@ -1137,7 +1137,7 @@ declare module Immutable { >Seq : typeof Seq function isSeq(maybeSeq: any): maybeSeq is Seq.Indexed | Seq.Keyed; ->isSeq : (maybeSeq: any) => maybeSeq is Keyed | Indexed +>isSeq : (maybeSeq: any) => maybeSeq is Indexed | Keyed >maybeSeq : any >Seq : any >Seq : any diff --git a/tests/baselines/reference/independentTypeParameter.js b/tests/baselines/reference/independentTypeParameter.js new file mode 100644 index 0000000000000..a89320b9dcd3c --- /dev/null +++ b/tests/baselines/reference/independentTypeParameter.js @@ -0,0 +1,12 @@ +//// [independentTypeParameter.ts] +// Repro for #26815 +interface Foo {} +function f(arg: Foo): T { return undefined!; } +let x: Foo = {}; +f(x); + + +//// [independentTypeParameter.js] +function f(arg) { return undefined; } +var x = {}; +f(x); diff --git a/tests/baselines/reference/independentTypeParameter.symbols b/tests/baselines/reference/independentTypeParameter.symbols new file mode 100644 index 0000000000000..9817dc08faa40 --- /dev/null +++ b/tests/baselines/reference/independentTypeParameter.symbols @@ -0,0 +1,23 @@ +=== tests/cases/compiler/independentTypeParameter.ts === +// Repro for #26815 +interface Foo {} +>Foo : Symbol(Foo, Decl(independentTypeParameter.ts, 0, 0)) +>T : Symbol(T, Decl(independentTypeParameter.ts, 1, 14)) + +function f(arg: Foo): T { return undefined!; } +>f : Symbol(f, Decl(independentTypeParameter.ts, 1, 19)) +>T : Symbol(T, Decl(independentTypeParameter.ts, 2, 11)) +>arg : Symbol(arg, Decl(independentTypeParameter.ts, 2, 14)) +>Foo : Symbol(Foo, Decl(independentTypeParameter.ts, 0, 0)) +>T : Symbol(T, Decl(independentTypeParameter.ts, 2, 11)) +>T : Symbol(T, Decl(independentTypeParameter.ts, 2, 11)) +>undefined : Symbol(undefined) + +let x: Foo = {}; +>x : Symbol(x, Decl(independentTypeParameter.ts, 3, 3)) +>Foo : Symbol(Foo, Decl(independentTypeParameter.ts, 0, 0)) + +f(x); +>f : Symbol(f, Decl(independentTypeParameter.ts, 1, 19)) +>x : Symbol(x, Decl(independentTypeParameter.ts, 3, 3)) + diff --git a/tests/baselines/reference/independentTypeParameter.types b/tests/baselines/reference/independentTypeParameter.types new file mode 100644 index 0000000000000..459de64bd2626 --- /dev/null +++ b/tests/baselines/reference/independentTypeParameter.types @@ -0,0 +1,18 @@ +=== tests/cases/compiler/independentTypeParameter.ts === +// Repro for #26815 +interface Foo {} +function f(arg: Foo): T { return undefined!; } +>f : (arg: Foo) => T +>arg : Foo +>undefined! : undefined +>undefined : undefined + +let x: Foo = {}; +>x : Foo +>{} : {} + +f(x); +>f(x) : {} +>f : (arg: Foo) => T +>x : Foo + diff --git a/tests/cases/compiler/independentTypeParameter.ts b/tests/cases/compiler/independentTypeParameter.ts new file mode 100644 index 0000000000000..3b1801bc194e5 --- /dev/null +++ b/tests/cases/compiler/independentTypeParameter.ts @@ -0,0 +1,5 @@ +// Repro for #26815 +interface Foo {} +function f(arg: Foo): T { return undefined!; } +let x: Foo = {}; +f(x); diff --git a/tests/cases/fourslash/genericCombinators3.ts b/tests/cases/fourslash/genericCombinators3.ts index bd6420cf37a2e..748f404ae5dca 100644 --- a/tests/cases/fourslash/genericCombinators3.ts +++ b/tests/cases/fourslash/genericCombinators3.ts @@ -1,6 +1,8 @@ /// ////interface Collection { +//// dummyT: T; +//// dummyU: U; ////} //// ////interface Combinators { diff --git a/tests/cases/fourslash/staticGenericOverloads1.ts b/tests/cases/fourslash/staticGenericOverloads1.ts index 7b15e6e2a3ed6..ddab9afef557f 100644 --- a/tests/cases/fourslash/staticGenericOverloads1.ts +++ b/tests/cases/fourslash/staticGenericOverloads1.ts @@ -1,6 +1,7 @@ /// ////class A { +//// dummy: T; //// static B(v: A): A; //// static B(v: S): A; //// static B(v: any): A {