Skip to content

Commit 7b85cd6

Browse files
authored
Numeric literals assignable to enum literals only when values match (#51561)
* Numeric literal assignable to enum literal only when values match * Accept new baselines * Update compiler sources * Accept new baselines * Fix test runner * Any numeric literal type is assignable to a computed numeric enum type
1 parent e99c935 commit 7b85cd6

14 files changed

+148
-47
lines changed

src/compiler/checker.ts

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ export const enum CheckMode {
386386

387387
/** @internal */
388388
export const enum SignatureCheckMode {
389+
None = 0,
389390
BivariantCallback = 1 << 0,
390391
StrictCallback = 1 << 1,
391392
IgnoreReturnTypes = 1 << 2,
@@ -476,7 +477,7 @@ function SymbolLinks(this: SymbolLinks) {
476477
}
477478

478479
function NodeLinks(this: NodeLinks) {
479-
this.flags = 0;
480+
this.flags = NodeCheckFlags.None;
480481
}
481482

482483
/** @internal */
@@ -1473,7 +1474,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
14731474
function createSymbol(flags: SymbolFlags, name: __String, checkFlags?: CheckFlags) {
14741475
symbolCount++;
14751476
const symbol = (new Symbol(flags | SymbolFlags.Transient, name) as TransientSymbol);
1476-
symbol.checkFlags = checkFlags || 0;
1477+
symbol.checkFlags = checkFlags || CheckFlags.None;
14771478
return symbol;
14781479
}
14791480

@@ -4543,7 +4544,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
45434544
return new Type(checker, flags);
45444545
}
45454546

4546-
function createIntrinsicType(kind: TypeFlags, intrinsicName: string, objectFlags: ObjectFlags = 0): IntrinsicType {
4547+
function createIntrinsicType(kind: TypeFlags, intrinsicName: string, objectFlags = ObjectFlags.None): IntrinsicType {
45474548
const type = createType(kind) as IntrinsicType;
45484549
type.intrinsicName = intrinsicName;
45494550
type.objectFlags = objectFlags;
@@ -8659,7 +8660,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
86598660

86608661
function formatUnionTypes(types: readonly Type[]): Type[] {
86618662
const result: Type[] = [];
8662-
let flags: TypeFlags = 0;
8663+
let flags = 0 as TypeFlags;
86638664
for (let i = 0; i < types.length; i++) {
86648665
const t = types[i];
86658666
flags |= t.flags;
@@ -14750,7 +14751,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1475014751
const minLength = countWhere(elementFlags, f => !!(f & (ElementFlags.Required | ElementFlags.Variadic)));
1475114752
let typeParameters: TypeParameter[] | undefined;
1475214753
const properties: Symbol[] = [];
14753-
let combinedFlags: ElementFlags = 0;
14754+
let combinedFlags = 0 as ElementFlags;
1475414755
if (arity) {
1475514756
typeParameters = new Array(arity);
1475614757
for (let i = 0; i < arity; i++) {
@@ -15114,7 +15115,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1511415115
return types[0];
1511515116
}
1511615117
let typeSet: Type[] | undefined = [];
15117-
const includes = addTypesToUnion(typeSet, 0, types);
15118+
const includes = addTypesToUnion(typeSet, 0 as TypeFlags, types);
1511815119
if (unionReduction !== UnionReduction.None) {
1511915120
if (includes & TypeFlags.AnyOrUnknown) {
1512015121
return includes & TypeFlags.Any ?
@@ -15429,7 +15430,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1542915430
// for intersections of types with signatures can be deterministic.
1543015431
function getIntersectionType(types: readonly Type[], aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], noSupertypeReduction?: boolean): Type {
1543115432
const typeMembershipMap: Map<string, Type> = new Map();
15432-
const includes = addTypesToIntersection(typeMembershipMap, 0, types);
15433+
const includes = addTypesToIntersection(typeMembershipMap, 0 as TypeFlags, types);
1543315434
const typeSet: Type[] = arrayFrom(typeMembershipMap.values());
1543415435
// An intersection type is considered empty if it contains
1543515436
// the type never, or
@@ -18441,7 +18442,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1844118442
function isSignatureAssignableTo(source: Signature,
1844218443
target: Signature,
1844318444
ignoreReturnTypes: boolean): boolean {
18444-
return compareSignaturesRelated(source, target, ignoreReturnTypes ? SignatureCheckMode.IgnoreReturnTypes : 0, /*reportErrors*/ false,
18445+
return compareSignaturesRelated(source, target, ignoreReturnTypes ? SignatureCheckMode.IgnoreReturnTypes : SignatureCheckMode.None, /*reportErrors*/ false,
1844518446
/*errorReporter*/ undefined, /*errorReporter*/ undefined, compareTypesAssignable, /*reportUnreliableMarkers*/ undefined) !== Ternary.False;
1844618447
}
1844718448

@@ -18757,11 +18758,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1875718758
if (s & TypeFlags.Object && t & TypeFlags.NonPrimitive && !(relation === strictSubtypeRelation && isEmptyAnonymousObjectType(source) && !(getObjectFlags(source) & ObjectFlags.FreshLiteral))) return true;
1875818759
if (relation === assignableRelation || relation === comparableRelation) {
1875918760
if (s & TypeFlags.Any) return true;
18760-
// Type number or any numeric literal type is assignable to any numeric enum type or any
18761-
// numeric enum literal type. This rule exists for backwards compatibility reasons because
18762-
// bit-flag enum types sometimes look like literal enum types with numeric literal values.
18763-
if (s & (TypeFlags.Number | TypeFlags.NumberLiteral) && !(s & TypeFlags.EnumLiteral) && (
18764-
t & TypeFlags.Enum || relation === assignableRelation && t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral)) return true;
18761+
// Type number is assignable to any computed numeric enum type or any numeric enum literal type, and
18762+
// a numeric literal type is assignable any computed numeric enum type or any numeric enum literal type
18763+
// with a matching value. These rules exist such that enums can be used for bit-flag purposes.
18764+
if (s & TypeFlags.Number && (t & TypeFlags.Enum || t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral)) return true;
18765+
if (s & TypeFlags.NumberLiteral && !(s & TypeFlags.EnumLiteral) && (t & TypeFlags.Enum ||
18766+
t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral &&
18767+
(source as NumberLiteralType).value === (target as NumberLiteralType).value)) return true;
1876518768
// Anything is assignable to a union containing undefined, null, and {}
1876618769
if (isUnknownLikeUnionType(target)) return true;
1876718770
}
@@ -19745,7 +19748,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1974519748
if (!(expandingFlags & ExpandingFlags.Target) && isDeeplyNestedType(target, targetStack, targetDepth)) expandingFlags |= ExpandingFlags.Target;
1974619749
}
1974719750
let originalHandler: typeof outofbandVarianceMarkerHandler;
19748-
let propagatingVarianceFlags: RelationComparisonResult = 0;
19751+
let propagatingVarianceFlags = 0 as RelationComparisonResult;
1974919752
if (outofbandVarianceMarkerHandler) {
1975019753
originalHandler = outofbandVarianceMarkerHandler;
1975119754
outofbandVarianceMarkerHandler = onlyUnreliable => {
@@ -22863,7 +22866,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2286322866
}
2286422867
}
2286522868

22866-
function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority: InferencePriority = 0, contravariant = false) {
22869+
function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority = InferencePriority.None, contravariant = false) {
2286722870
let bivariant = false;
2286822871
let propagationType: Type;
2286922872
let inferencePriority: number = InferencePriority.MaxValue;

src/compiler/transformers/es2015.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ interface LoopOutParameter {
8888
}
8989

9090
const enum LoopOutParameterFlags {
91+
None = 0,
9192
Body = 1 << 0, // Modified in the body of the iteration statement
9293
Initializer = 1 << 1, // Set in the initializer of a ForStatement
9394
}
@@ -3488,7 +3489,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile
34883489
const checkFlags = resolver.getNodeCheckFlags(decl);
34893490
if (checkFlags & NodeCheckFlags.NeedsLoopOutParameter || hasCapturedBindingsInForHead) {
34903491
const outParamName = factory.createUniqueName("out_" + idText(name));
3491-
let flags: LoopOutParameterFlags = 0;
3492+
let flags = LoopOutParameterFlags.None;
34923493
if (checkFlags & NodeCheckFlags.NeedsLoopOutParameter) {
34933494
flags |= LoopOutParameterFlags.Body;
34943495
}

src/compiler/transformers/es2017.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const enum ES2017SubstitutionFlags {
2525
}
2626

2727
const enum ContextFlags {
28+
None = 0,
2829
NonTopLevel = 1 << 0,
2930
HasLexicalThis = 1 << 1
3031
}
@@ -66,7 +67,7 @@ export function transformES2017(context: TransformationContext): (x: SourceFile
6667
/** A set of node IDs for generated super accessors (variable statements). */
6768
const substitutedSuperAccessors: boolean[] = [];
6869

69-
let contextFlags: ContextFlags = 0;
70+
let contextFlags = ContextFlags.None;
7071

7172
// Save the previous transformation hooks.
7273
const previousOnEmitNode = context.onEmitNode;

src/compiler/types.ts

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5514,6 +5514,7 @@ export const enum EnumKind {
55145514

55155515
/** @internal */
55165516
export const enum CheckFlags {
5517+
None = 0,
55175518
Instantiated = 1 << 0, // Instantiated symbol
55185519
SyntheticProperty = 1 << 1, // Property in union or intersection type
55195520
SyntheticMethod = 1 << 2, // Method in union or intersection type
@@ -5611,31 +5612,32 @@ export interface PatternAmbientModule {
56115612

56125613
/** @internal */
56135614
export const enum NodeCheckFlags {
5614-
TypeChecked = 0x00000001, // Node has been type checked
5615-
LexicalThis = 0x00000002, // Lexical 'this' reference
5616-
CaptureThis = 0x00000004, // Lexical 'this' used in body
5617-
CaptureNewTarget = 0x00000008, // Lexical 'new.target' used in body
5618-
SuperInstance = 0x00000100, // Instance 'super' reference
5619-
SuperStatic = 0x00000200, // Static 'super' reference
5620-
ContextChecked = 0x00000400, // Contextual types have been assigned
5621-
MethodWithSuperPropertyAccessInAsync = 0x00000800, // A method that contains a SuperProperty access in an async context.
5622-
MethodWithSuperPropertyAssignmentInAsync = 0x00001000, // A method that contains a SuperProperty assignment in an async context.
5623-
CaptureArguments = 0x00002000, // Lexical 'arguments' used in body
5624-
EnumValuesComputed = 0x00004000, // Values for enum members have been computed, and any errors have been reported for them.
5625-
LexicalModuleMergesWithClass = 0x00008000, // Instantiated lexical module declaration is merged with a previous class declaration.
5626-
LoopWithCapturedBlockScopedBinding = 0x00010000, // Loop that contains block scoped variable captured in closure
5627-
ContainsCapturedBlockScopeBinding = 0x00020000, // Part of a loop that contains block scoped variable captured in closure
5628-
CapturedBlockScopedBinding = 0x00040000, // Block-scoped binding that is captured in some function
5629-
BlockScopedBindingInLoop = 0x00080000, // Block-scoped binding with declaration nested inside iteration statement
5630-
ClassWithBodyScopedClassBinding = 0x00100000, // Decorated class that contains a binding to itself inside of the class body.
5631-
BodyScopedClassBinding = 0x00200000, // Binding to a decorated class inside of the class's body.
5632-
NeedsLoopOutParameter = 0x00400000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
5633-
AssignmentsMarked = 0x00800000, // Parameter assignments have been marked
5634-
ClassWithConstructorReference = 0x01000000, // Class that contains a binding to its constructor inside of the class body.
5635-
ConstructorReferenceInClass = 0x02000000, // Binding to a class constructor inside of the class's body.
5636-
ContainsClassWithPrivateIdentifiers = 0x04000000, // Marked on all block-scoped containers containing a class with private identifiers.
5637-
ContainsSuperPropertyInStaticInitializer = 0x08000000, // Marked on all block-scoped containers containing a static initializer with 'super.x' or 'super[x]'.
5638-
InCheckIdentifier = 0x10000000,
5615+
None = 0,
5616+
TypeChecked = 1 << 0, // Node has been type checked
5617+
LexicalThis = 1 << 1, // Lexical 'this' reference
5618+
CaptureThis = 1 << 2, // Lexical 'this' used in body
5619+
CaptureNewTarget = 1 << 3, // Lexical 'new.target' used in body
5620+
SuperInstance = 1 << 4, // Instance 'super' reference
5621+
SuperStatic = 1 << 5, // Static 'super' reference
5622+
ContextChecked = 1 << 6, // Contextual types have been assigned
5623+
MethodWithSuperPropertyAccessInAsync = 1 << 7, // A method that contains a SuperProperty access in an async context.
5624+
MethodWithSuperPropertyAssignmentInAsync = 1 << 8, // A method that contains a SuperProperty assignment in an async context.
5625+
CaptureArguments = 1 << 9, // Lexical 'arguments' used in body
5626+
EnumValuesComputed = 1 << 10, // Values for enum members have been computed, and any errors have been reported for them.
5627+
LexicalModuleMergesWithClass = 1 << 11, // Instantiated lexical module declaration is merged with a previous class declaration.
5628+
LoopWithCapturedBlockScopedBinding = 1 << 12, // Loop that contains block scoped variable captured in closure
5629+
ContainsCapturedBlockScopeBinding = 1 << 13, // Part of a loop that contains block scoped variable captured in closure
5630+
CapturedBlockScopedBinding = 1 << 14, // Block-scoped binding that is captured in some function
5631+
BlockScopedBindingInLoop = 1 << 15, // Block-scoped binding with declaration nested inside iteration statement
5632+
ClassWithBodyScopedClassBinding = 1 << 16, // Decorated class that contains a binding to itself inside of the class body.
5633+
BodyScopedClassBinding = 1 << 17, // Binding to a decorated class inside of the class's body.
5634+
NeedsLoopOutParameter = 1 << 18, // Block scoped binding whose value should be explicitly copied outside of the converted loop
5635+
AssignmentsMarked = 1 << 19, // Parameter assignments have been marked
5636+
ClassWithConstructorReference = 1 << 20, // Class that contains a binding to its constructor inside of the class body.
5637+
ConstructorReferenceInClass = 1 << 21, // Binding to a class constructor inside of the class's body.
5638+
ContainsClassWithPrivateIdentifiers = 1 << 22, // Marked on all block-scoped containers containing a class with private identifiers.
5639+
ContainsSuperPropertyInStaticInitializer = 1 << 23, // Marked on all block-scoped containers containing a static initializer with 'super.x' or 'super[x]'.
5640+
InCheckIdentifier = 1 << 24,
56395641
}
56405642

56415643
/** @internal */
@@ -5842,6 +5844,7 @@ export interface EnumType extends Type {
58425844
// are specific to certain types and reuse the same bit position. Those ObjectFlags require a check
58435845
// for a certain TypeFlags value to determine their meaning.
58445846
export const enum ObjectFlags {
5847+
None = 0,
58455848
Class = 1 << 0, // Class
58465849
Interface = 1 << 1, // Interface
58475850
Reference = 1 << 2, // Generic type reference
@@ -6384,6 +6387,7 @@ export type TypeMapper =
63846387
| { kind: TypeMapKind.Composite | TypeMapKind.Merged, mapper1: TypeMapper, mapper2: TypeMapper };
63856388

63866389
export const enum InferencePriority {
6390+
None = 0,
63876391
NakedTypeVariable = 1 << 0, // Naked type variable in union or intersection type
63886392
SpeculativeTuple = 1 << 1, // Speculative tuple inference
63896393
SubstituteSource = 1 << 2, // Source of inference originated within a substitution type's substitute

src/services/formatting/rule.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export const anyContext: readonly ContextPredicate[] = emptyArray;
1717

1818
/** @internal */
1919
export const enum RuleAction {
20+
None = 0,
2021
StopProcessingSpaceActions = 1 << 0,
2122
StopProcessingTokenActions = 1 << 1,
2223
InsertSpace = 1 << 2,

src/services/formatting/rulesMap.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function getRulesMap(): RulesMap {
2222
* cannot be applied at the same position.
2323
*/
2424
function getRuleActionExclusion(ruleAction: RuleAction): RuleAction {
25-
let mask: RuleAction = 0;
25+
let mask = RuleAction.None;
2626
if (ruleAction & RuleAction.StopProcessingSpaceActions) {
2727
mask |= RuleAction.ModifySpaceAction;
2828
}

src/testRunner/unittests/helpers.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as ts from "../_namespaces/ts";
22

33
const enum ChangedPart {
4+
none = 0,
45
references = 1 << 0,
56
importsAndExports = 1 << 1,
67
program = 1 << 2
@@ -32,7 +33,7 @@ export class SourceText implements ts.IScriptSnapshot {
3233
constructor(private references: string,
3334
private importsAndExports: string,
3435
private program: string,
35-
private changedPart: ChangedPart = 0,
36+
private changedPart = ChangedPart.none,
3637
private version = 0) {
3738
}
3839

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6719,6 +6719,7 @@ declare namespace ts {
67196719
interface EnumType extends Type {
67206720
}
67216721
enum ObjectFlags {
6722+
None = 0,
67226723
Class = 1,
67236724
Interface = 2,
67246725
Reference = 4,
@@ -6889,6 +6890,7 @@ declare namespace ts {
68896890
declaration?: IndexSignatureDeclaration;
68906891
}
68916892
enum InferencePriority {
6893+
None = 0,
68926894
NakedTypeVariable = 1,
68936895
SpeculativeTuple = 2,
68946896
SubstituteSource = 4,

tests/baselines/reference/api/typescript.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2783,6 +2783,7 @@ declare namespace ts {
27832783
interface EnumType extends Type {
27842784
}
27852785
enum ObjectFlags {
2786+
None = 0,
27862787
Class = 1,
27872788
Interface = 2,
27882789
Reference = 4,
@@ -2953,6 +2954,7 @@ declare namespace ts {
29532954
declaration?: IndexSignatureDeclaration;
29542955
}
29552956
enum InferencePriority {
2957+
None = 0,
29562958
NakedTypeVariable = 1,
29572959
SpeculativeTuple = 2,
29582960
SubstituteSource = 4,

0 commit comments

Comments
 (0)