Skip to content
This repository was archived by the owner on Mar 12, 2025. It is now read-only.

Commit d6dc481

Browse files
authored
feat(ts/analyzer): Use never for unconditional throws (#412)
1 parent acd622f commit d6dc481

File tree

6 files changed

+59
-10
lines changed

6 files changed

+59
-10
lines changed

crates/stc_ts_file_analyzer/src/analyzer/stmt/return_type.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ impl Analyzer<'_, '_> {
6969
debug!("visit_stmts_for_return()");
7070
debug_assert!(!self.is_builtin, "builtin: visit_stmts_for_return should not be called");
7171

72+
let mut unconditional_throw = None;
73+
for stmt in stmts {
74+
if let RStmt::Throw(throws) = stmt {
75+
unconditional_throw = Some(throws.span);
76+
break;
77+
}
78+
}
79+
7280
let cannot_fallback_to_iterable_iterator = self.rule().strict_null_checks && {
7381
let mut v = YieldValueUsageFinder::default();
7482

@@ -95,13 +103,7 @@ impl Analyzer<'_, '_> {
95103

96104
{
97105
// Expand return types if no element references a type parameter
98-
let can_expand = values.return_types.iter().all(|ty| {
99-
if should_preserve_ref(ty) {
100-
return false;
101-
}
102-
103-
true
104-
});
106+
let can_expand = !values.return_types.iter().any(should_preserve_ref);
105107

106108
if can_expand {
107109
values.return_types = values
@@ -149,6 +151,12 @@ impl Analyzer<'_, '_> {
149151
}
150152
}
151153

154+
{
155+
if let Some(span) = unconditional_throw {
156+
values.return_types.push(Type::never(span, Default::default()));
157+
}
158+
}
159+
152160
debug!("visit_stmts_for_return: types.len() = {}", values.return_types.len());
153161

154162
let mut actual = Vec::with_capacity(values.return_types.len());
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
x Type
3+
,-[$DIR/tests/pass/fn/impl/1.ts:1:1]
4+
1 | undefined === function(): number {
5+
: ^^^^^^^^^
6+
`----
7+
8+
Error:
9+
> undefined
10+
11+
x Type
12+
,-[$DIR/tests/pass/fn/impl/1.ts:2:3]
13+
2 | throw undefined
14+
: ^^^^^^^^^
15+
`----
16+
17+
Error:
18+
> undefined
19+
20+
x Type
21+
,-[$DIR/tests/pass/fn/impl/1.ts:1:1]
22+
1 | ,-> undefined === function(): number {
23+
2 | | throw undefined
24+
3 | `-> }
25+
`----
26+
27+
Error:
28+
> () => number
29+
30+
x Type
31+
,-[$DIR/tests/pass/fn/impl/1.ts:1:1]
32+
1 | ,-> undefined === function(): number {
33+
2 | | throw undefined
34+
3 | `-> }
35+
`----
36+
37+
Error:
38+
> boolean
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
undefined === function(): number {
2+
throw undefined
3+
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Stats {
22
required_error: 3,
33
matched_error: 1,
4-
extra_error: 1,
4+
extra_error: 0,
55
panic: 0,
66
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Stats {
22
required_error: 1,
33
matched_error: 0,
4-
extra_error: 4,
4+
extra_error: 3,
55
panic: 0,
66
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Stats {
22
required_error: 0,
33
matched_error: 0,
4-
extra_error: 3,
4+
extra_error: 2,
55
panic: 0,
66
}

0 commit comments

Comments
 (0)