From d877b05aefe4652dee1ef5a3ee66ee17d556a817 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 16 May 2025 07:07:20 -0700 Subject: [PATCH 1/3] Add missing bounds check in isReachableFlowNodeWorker --- internal/checker/flow.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/internal/checker/flow.go b/internal/checker/flow.go index 58dcf30b9c..6a96a355d8 100644 --- a/internal/checker/flow.go +++ b/internal/checker/flow.go @@ -2484,13 +2484,12 @@ func (c *Checker) isReachableFlowNodeWorker(f *FlowState, flow *ast.FlowNode, no case flags&(ast.FlowFlagsAssignment|ast.FlowFlagsCondition|ast.FlowFlagsArrayMutation) != 0: flow = flow.Antecedent case flags&ast.FlowFlagsCall != 0: - signature := c.getEffectsSignature(flow.Node) - if signature != nil { - predicate := c.getTypePredicateOfSignature(signature) - if predicate != nil && predicate.kind == TypePredicateKindAssertsIdentifier && predicate.t == nil { - predicateArgument := flow.Node.Arguments()[predicate.parameterIndex] - if predicateArgument != nil && c.isFalseExpression(predicateArgument) { - return false + if signature := c.getEffectsSignature(flow.Node); signature != nil { + if predicate := c.getTypePredicateOfSignature(signature); predicate != nil && predicate.kind == TypePredicateKindAssertsIdentifier && predicate.t == nil { + if arguments := flow.Node.Arguments(); int(predicate.parameterIndex) < len(arguments) { + if predicateArgument := arguments[predicate.parameterIndex]; predicateArgument != nil && c.isFalseExpression(predicateArgument) { + return false + } } } if c.getReturnTypeOfSignature(signature).flags&TypeFlagsNever != 0 { From 31135434871c418b7d125c9a331c70cb381b4576 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 16 May 2025 07:29:45 -0700 Subject: [PATCH 2/3] Add regression test --- .../compiler/assertionWithNoArgument.symbols | 15 +++++++++++++++ .../compiler/assertionWithNoArgument.types | 17 +++++++++++++++++ .../cases/compiler/assertionWithNoArgument.ts | 8 ++++++++ 3 files changed, 40 insertions(+) create mode 100644 testdata/baselines/reference/compiler/assertionWithNoArgument.symbols create mode 100644 testdata/baselines/reference/compiler/assertionWithNoArgument.types create mode 100644 testdata/tests/cases/compiler/assertionWithNoArgument.ts diff --git a/testdata/baselines/reference/compiler/assertionWithNoArgument.symbols b/testdata/baselines/reference/compiler/assertionWithNoArgument.symbols new file mode 100644 index 0000000000..b94aad1456 --- /dev/null +++ b/testdata/baselines/reference/compiler/assertionWithNoArgument.symbols @@ -0,0 +1,15 @@ +//// [tests/cases/compiler/assertionWithNoArgument.ts] //// + +=== assertionWithNoArgument.ts === +export function assertWeird(value?: string): asserts value { +>assertWeird : Symbol(assertWeird, Decl(assertionWithNoArgument.ts, 0, 0)) +>value : Symbol(value, Decl(assertionWithNoArgument.ts, 0, 28)) +>value : Symbol(value, Decl(assertionWithNoArgument.ts, 0, 28)) +} + +assertWeird(); +>assertWeird : Symbol(assertWeird, Decl(assertionWithNoArgument.ts, 0, 0)) + +assertWeird("hello"); +>assertWeird : Symbol(assertWeird, Decl(assertionWithNoArgument.ts, 0, 0)) + diff --git a/testdata/baselines/reference/compiler/assertionWithNoArgument.types b/testdata/baselines/reference/compiler/assertionWithNoArgument.types new file mode 100644 index 0000000000..51ac01d907 --- /dev/null +++ b/testdata/baselines/reference/compiler/assertionWithNoArgument.types @@ -0,0 +1,17 @@ +//// [tests/cases/compiler/assertionWithNoArgument.ts] //// + +=== assertionWithNoArgument.ts === +export function assertWeird(value?: string): asserts value { +>assertWeird : (value?: string | undefined) => asserts value +>value : string | undefined +} + +assertWeird(); +>assertWeird() : void +>assertWeird : (value?: string | undefined) => asserts value + +assertWeird("hello"); +>assertWeird("hello") : void +>assertWeird : (value?: string | undefined) => asserts value +>"hello" : "hello" + diff --git a/testdata/tests/cases/compiler/assertionWithNoArgument.ts b/testdata/tests/cases/compiler/assertionWithNoArgument.ts new file mode 100644 index 0000000000..9b33913fc1 --- /dev/null +++ b/testdata/tests/cases/compiler/assertionWithNoArgument.ts @@ -0,0 +1,8 @@ +// @strict: true +// @noemit: true + +export function assertWeird(value?: string): asserts value { +} + +assertWeird(); +assertWeird("hello"); From 5f2161b12c7281b9b57ebed6f147be83a4a112e8 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 16 May 2025 09:12:30 -0700 Subject: [PATCH 3/3] Address CR feedback --- internal/checker/flow.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/internal/checker/flow.go b/internal/checker/flow.go index 6a96a355d8..e8d9daec2e 100644 --- a/internal/checker/flow.go +++ b/internal/checker/flow.go @@ -2486,10 +2486,8 @@ func (c *Checker) isReachableFlowNodeWorker(f *FlowState, flow *ast.FlowNode, no case flags&ast.FlowFlagsCall != 0: if signature := c.getEffectsSignature(flow.Node); signature != nil { if predicate := c.getTypePredicateOfSignature(signature); predicate != nil && predicate.kind == TypePredicateKindAssertsIdentifier && predicate.t == nil { - if arguments := flow.Node.Arguments(); int(predicate.parameterIndex) < len(arguments) { - if predicateArgument := arguments[predicate.parameterIndex]; predicateArgument != nil && c.isFalseExpression(predicateArgument) { - return false - } + if arguments := flow.Node.Arguments(); int(predicate.parameterIndex) < len(arguments) && c.isFalseExpression(arguments[predicate.parameterIndex]) { + return false } } if c.getReturnTypeOfSignature(signature).flags&TypeFlagsNever != 0 {