From 79e0c3acb43bb982ad0fc9f3b51bfe946624a128 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 15 Nov 2023 17:26:13 -0500 Subject: [PATCH] Allow variance annotations on generic references --- src/compiler/checker.ts | 2 +- .../reference/varianceReferences.errors.txt | 42 +++++++++ .../baselines/reference/varianceReferences.js | 35 +++++++ .../reference/varianceReferences.symbols | 92 +++++++++++++++++++ .../reference/varianceReferences.types | 51 ++++++++++ tests/cases/compiler/varianceReferences.ts | 29 ++++++ 6 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/varianceReferences.errors.txt create mode 100644 tests/baselines/reference/varianceReferences.js create mode 100644 tests/baselines/reference/varianceReferences.symbols create mode 100644 tests/baselines/reference/varianceReferences.types create mode 100644 tests/cases/compiler/varianceReferences.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4a294a2474f26..ade6dea7f7e2c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -39137,7 +39137,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const modifiers = getTypeParameterModifiers(typeParameter) & (ModifierFlags.In | ModifierFlags.Out); if (modifiers) { const symbol = getSymbolOfDeclaration(node.parent); - if (isTypeAliasDeclaration(node.parent) && !(getObjectFlags(getDeclaredTypeOfSymbol(symbol)) & (ObjectFlags.Anonymous | ObjectFlags.Mapped))) { + if (isTypeAliasDeclaration(node.parent) && !(getObjectFlags(getDeclaredTypeOfSymbol(symbol)) & (ObjectFlags.Reference | ObjectFlags.Anonymous | ObjectFlags.Mapped))) { error(node, Diagnostics.Variance_annotations_are_only_supported_in_type_aliases_for_object_function_constructor_and_mapped_types); } else if (modifiers === ModifierFlags.In || modifiers === ModifierFlags.Out) { diff --git a/tests/baselines/reference/varianceReferences.errors.txt b/tests/baselines/reference/varianceReferences.errors.txt new file mode 100644 index 0000000000000..25d23697fba79 --- /dev/null +++ b/tests/baselines/reference/varianceReferences.errors.txt @@ -0,0 +1,42 @@ +varianceReferences.ts(3,32): error TS2637: Variance annotations are only supported in type aliases for object, function, constructor, and mapped types. +varianceReferences.ts(8,28): error TS2637: Variance annotations are only supported in type aliases for object, function, constructor, and mapped types. +varianceReferences.ts(14,32): error TS2637: Variance annotations are only supported in type aliases for object, function, constructor, and mapped types. + + +==== varianceReferences.ts (3 errors) ==== + type NumericConstraint = Value; + + type VarianceConstrainedNumber = + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2637: Variance annotations are only supported in type aliases for object, function, constructor, and mapped types. + NumericConstraint; + + type Unconstrained = Value; + + type VarianceUnconstrained = Unconstrained; + ~~~~~~~~~~~~ +!!! error TS2637: Variance annotations are only supported in type aliases for object, function, constructor, and mapped types. + + type Level3of3Unconstrained = Value; + type Level2of3Unconstrained = Level3of3Unconstrained; + type Level1of3Unconstrained = Level2of3Unconstrained; + + type VarianceDeepUnconstrained = Level1of3Unconstrained; + ~~~~~~~~~~~~ +!!! error TS2637: Variance annotations are only supported in type aliases for object, function, constructor, and mapped types. + + interface Shape { + value: Value; + } + + type VarianceShape = Shape; + + interface Level3of3Shape { + value: Value; + } + + type Level2of3Shape = Level3of3Shape; + type Level1of3Shape = Level2of3Shape; + + type VarianceDeepShape = Level1of3Shape; + \ No newline at end of file diff --git a/tests/baselines/reference/varianceReferences.js b/tests/baselines/reference/varianceReferences.js new file mode 100644 index 0000000000000..12d717da01a50 --- /dev/null +++ b/tests/baselines/reference/varianceReferences.js @@ -0,0 +1,35 @@ +//// [tests/cases/compiler/varianceReferences.ts] //// + +//// [varianceReferences.ts] +type NumericConstraint = Value; + +type VarianceConstrainedNumber = + NumericConstraint; + +type Unconstrained = Value; + +type VarianceUnconstrained = Unconstrained; + +type Level3of3Unconstrained = Value; +type Level2of3Unconstrained = Level3of3Unconstrained; +type Level1of3Unconstrained = Level2of3Unconstrained; + +type VarianceDeepUnconstrained = Level1of3Unconstrained; + +interface Shape { + value: Value; +} + +type VarianceShape = Shape; + +interface Level3of3Shape { + value: Value; +} + +type Level2of3Shape = Level3of3Shape; +type Level1of3Shape = Level2of3Shape; + +type VarianceDeepShape = Level1of3Shape; + + +//// [varianceReferences.js] diff --git a/tests/baselines/reference/varianceReferences.symbols b/tests/baselines/reference/varianceReferences.symbols new file mode 100644 index 0000000000000..275f3193bf3cc --- /dev/null +++ b/tests/baselines/reference/varianceReferences.symbols @@ -0,0 +1,92 @@ +//// [tests/cases/compiler/varianceReferences.ts] //// + +=== varianceReferences.ts === +type NumericConstraint = Value; +>NumericConstraint : Symbol(NumericConstraint, Decl(varianceReferences.ts, 0, 0)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 0, 23)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 0, 23)) + +type VarianceConstrainedNumber = +>VarianceConstrainedNumber : Symbol(VarianceConstrainedNumber, Decl(varianceReferences.ts, 0, 53)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 2, 31)) + + NumericConstraint; +>NumericConstraint : Symbol(NumericConstraint, Decl(varianceReferences.ts, 0, 0)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 2, 31)) + +type Unconstrained = Value; +>Unconstrained : Symbol(Unconstrained, Decl(varianceReferences.ts, 3, 27)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 5, 19)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 5, 19)) + +type VarianceUnconstrained = Unconstrained; +>VarianceUnconstrained : Symbol(VarianceUnconstrained, Decl(varianceReferences.ts, 5, 34)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 7, 27)) +>Unconstrained : Symbol(Unconstrained, Decl(varianceReferences.ts, 3, 27)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 7, 27)) + +type Level3of3Unconstrained = Value; +>Level3of3Unconstrained : Symbol(Level3of3Unconstrained, Decl(varianceReferences.ts, 7, 64)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 9, 28)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 9, 28)) + +type Level2of3Unconstrained = Level3of3Unconstrained; +>Level2of3Unconstrained : Symbol(Level2of3Unconstrained, Decl(varianceReferences.ts, 9, 43)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 10, 28)) +>Level3of3Unconstrained : Symbol(Level3of3Unconstrained, Decl(varianceReferences.ts, 7, 64)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 10, 28)) + +type Level1of3Unconstrained = Level2of3Unconstrained; +>Level1of3Unconstrained : Symbol(Level1of3Unconstrained, Decl(varianceReferences.ts, 10, 67)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 11, 28)) +>Level2of3Unconstrained : Symbol(Level2of3Unconstrained, Decl(varianceReferences.ts, 9, 43)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 11, 28)) + +type VarianceDeepUnconstrained = Level1of3Unconstrained; +>VarianceDeepUnconstrained : Symbol(VarianceDeepUnconstrained, Decl(varianceReferences.ts, 11, 67)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 13, 31)) +>Level1of3Unconstrained : Symbol(Level1of3Unconstrained, Decl(varianceReferences.ts, 10, 67)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 13, 31)) + +interface Shape { +>Shape : Symbol(Shape, Decl(varianceReferences.ts, 13, 77)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 15, 16)) + + value: Value; +>value : Symbol(Shape.value, Decl(varianceReferences.ts, 15, 24)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 15, 16)) +} + +type VarianceShape = Shape; +>VarianceShape : Symbol(VarianceShape, Decl(varianceReferences.ts, 17, 1)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 19, 19)) +>Shape : Symbol(Shape, Decl(varianceReferences.ts, 13, 77)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 19, 19)) + +interface Level3of3Shape { +>Level3of3Shape : Symbol(Level3of3Shape, Decl(varianceReferences.ts, 19, 48)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 21, 25)) + + value: Value; +>value : Symbol(Level3of3Shape.value, Decl(varianceReferences.ts, 21, 33)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 21, 25)) +} + +type Level2of3Shape = Level3of3Shape; +>Level2of3Shape : Symbol(Level2of3Shape, Decl(varianceReferences.ts, 23, 1)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 25, 20)) +>Level3of3Shape : Symbol(Level3of3Shape, Decl(varianceReferences.ts, 19, 48)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 25, 20)) + +type Level1of3Shape = Level2of3Shape; +>Level1of3Shape : Symbol(Level1of3Shape, Decl(varianceReferences.ts, 25, 51)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 26, 20)) +>Level2of3Shape : Symbol(Level2of3Shape, Decl(varianceReferences.ts, 23, 1)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 26, 20)) + +type VarianceDeepShape = Level1of3Shape; +>VarianceDeepShape : Symbol(VarianceDeepShape, Decl(varianceReferences.ts, 26, 51)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 28, 23)) +>Level1of3Shape : Symbol(Level1of3Shape, Decl(varianceReferences.ts, 25, 51)) +>Value : Symbol(Value, Decl(varianceReferences.ts, 28, 23)) + diff --git a/tests/baselines/reference/varianceReferences.types b/tests/baselines/reference/varianceReferences.types new file mode 100644 index 0000000000000..5ecc8436aa686 --- /dev/null +++ b/tests/baselines/reference/varianceReferences.types @@ -0,0 +1,51 @@ +//// [tests/cases/compiler/varianceReferences.ts] //// + +=== varianceReferences.ts === +type NumericConstraint = Value; +>NumericConstraint : Value + +type VarianceConstrainedNumber = +>VarianceConstrainedNumber : Value + + NumericConstraint; + +type Unconstrained = Value; +>Unconstrained : Value + +type VarianceUnconstrained = Unconstrained; +>VarianceUnconstrained : Value + +type Level3of3Unconstrained = Value; +>Level3of3Unconstrained : Value + +type Level2of3Unconstrained = Level3of3Unconstrained; +>Level2of3Unconstrained : Value + +type Level1of3Unconstrained = Level2of3Unconstrained; +>Level1of3Unconstrained : Value + +type VarianceDeepUnconstrained = Level1of3Unconstrained; +>VarianceDeepUnconstrained : Value + +interface Shape { + value: Value; +>value : Value +} + +type VarianceShape = Shape; +>VarianceShape : VarianceShape + +interface Level3of3Shape { + value: Value; +>value : Value +} + +type Level2of3Shape = Level3of3Shape; +>Level2of3Shape : Level2of3Shape + +type Level1of3Shape = Level2of3Shape; +>Level1of3Shape : Level1of3Shape + +type VarianceDeepShape = Level1of3Shape; +>VarianceDeepShape : VarianceDeepShape + diff --git a/tests/cases/compiler/varianceReferences.ts b/tests/cases/compiler/varianceReferences.ts new file mode 100644 index 0000000000000..a31f34df33206 --- /dev/null +++ b/tests/cases/compiler/varianceReferences.ts @@ -0,0 +1,29 @@ +type NumericConstraint = Value; + +type VarianceConstrainedNumber = + NumericConstraint; + +type Unconstrained = Value; + +type VarianceUnconstrained = Unconstrained; + +type Level3of3Unconstrained = Value; +type Level2of3Unconstrained = Level3of3Unconstrained; +type Level1of3Unconstrained = Level2of3Unconstrained; + +type VarianceDeepUnconstrained = Level1of3Unconstrained; + +interface Shape { + value: Value; +} + +type VarianceShape = Shape; + +interface Level3of3Shape { + value: Value; +} + +type Level2of3Shape = Level3of3Shape; +type Level1of3Shape = Level2of3Shape; + +type VarianceDeepShape = Level1of3Shape;