Skip to content

Commit 89f176d

Browse files
GearsDatapackslpil
authored andcommitted
Properly take into account type variables in let bindings
1 parent 5eab96e commit 89f176d

File tree

4 files changed

+74
-136
lines changed

4 files changed

+74
-136
lines changed

compiler-core/src/ast/visit.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -996,12 +996,21 @@ pub fn visit_typed_expr_fn<'a, V>(
996996
_location: &'a SrcSpan,
997997
_type_: &'a Arc<Type>,
998998
_kind: &'a FunctionLiteralKind,
999-
_arguments: &'a [TypedArg],
999+
arguments: &'a [TypedArg],
10001000
body: &'a Vec1<TypedStatement>,
1001-
_return_annotation: &'a Option<TypeAst>,
1001+
return_annotation: &'a Option<TypeAst>,
10021002
) where
10031003
V: Visit<'a> + ?Sized,
10041004
{
1005+
for argument in arguments {
1006+
if let Some(annotation) = &argument.annotation {
1007+
v.visit_type_ast(annotation);
1008+
}
1009+
}
1010+
if let Some(return_) = return_annotation {
1011+
v.visit_type_ast(return_);
1012+
}
1013+
10051014
for stmt in body {
10061015
v.visit_typed_statement(stmt);
10071016
}
@@ -1237,6 +1246,9 @@ pub fn visit_typed_assignment<'a, V>(v: &mut V, assignment: &'a TypedAssignment)
12371246
where
12381247
V: Visit<'a> + ?Sized,
12391248
{
1249+
if let Some(annotation) = &assignment.annotation {
1250+
v.visit_type_ast(annotation);
1251+
}
12401252
v.visit_typed_expr(&assignment.value);
12411253
v.visit_typed_pattern(&assignment.pattern);
12421254
}

compiler-core/src/language_server/code_action.rs

Lines changed: 21 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,13 +1194,13 @@ impl<'ast> ast::visit::Visit<'ast> for AddAnnotations<'_> {
11941194
}
11951195

11961196
fn visit_typed_function(&mut self, fun: &'ast ast::TypedFunction) {
1197-
self.printer.clear_type_variables();
1198-
11991197
// Since type variable names are local to definitions, any type variables
12001198
// in other parts of the module shouldn't affect what we print for the
12011199
// annotations of this functions. The only variables which cannot clash
12021200
// are ones defined in the signature of this function, which we register
1203-
// when we visit the parameters of this function below.
1201+
// when we visit the parameters of this function inside `collect_type_variables`.
1202+
self.printer.clear_type_variables();
1203+
collect_type_variables(&mut self.printer, fun);
12041204

12051205
ast::visit::visit_typed_function(self, fun);
12061206

@@ -1240,12 +1240,6 @@ impl<'ast> ast::visit::Visit<'ast> for AddAnnotations<'_> {
12401240
}
12411241
}
12421242

1243-
fn visit_type_ast_var(&mut self, _location: &'ast SrcSpan, name: &'ast EcoString) {
1244-
// Register this type variable so that we don't duplicate names when
1245-
// adding annotations.
1246-
self.printer.register_type_variable(name.clone());
1247-
}
1248-
12491243
fn visit_typed_expr_fn(
12501244
&mut self,
12511245
location: &'ast SrcSpan,
@@ -1340,6 +1334,24 @@ impl<'a> AddAnnotations<'a> {
13401334
}
13411335
}
13421336

1337+
struct TypeVariableCollector<'a, 'b> {
1338+
printer: &'a mut Printer<'b>,
1339+
}
1340+
1341+
/// Collect type variables defined within a function and register them for a
1342+
/// `Printer`
1343+
fn collect_type_variables(printer: &mut Printer<'_>, function: &ast::TypedFunction) {
1344+
TypeVariableCollector { printer }.visit_typed_function(function);
1345+
}
1346+
1347+
impl<'ast, 'a, 'b> ast::visit::Visit<'ast> for TypeVariableCollector<'a, 'b> {
1348+
fn visit_type_ast_var(&mut self, _location: &'ast SrcSpan, name: &'ast EcoString) {
1349+
// Register this type variable so that we don't duplicate names when
1350+
// adding annotations.
1351+
self.printer.register_type_variable(name.clone());
1352+
}
1353+
}
1354+
13431355
pub struct QualifiedConstructor<'a> {
13441356
import: &'a Import<EcoString>,
13451357
used_name: EcoString,
@@ -1411,34 +1423,6 @@ impl<'a> QualifiedToUnqualifiedImportFirstPass<'a> {
14111423
}
14121424

14131425
impl<'ast> ast::visit::Visit<'ast> for QualifiedToUnqualifiedImportFirstPass<'ast> {
1414-
fn visit_typed_expr_fn(
1415-
&mut self,
1416-
location: &'ast SrcSpan,
1417-
type_: &'ast Arc<Type>,
1418-
kind: &'ast FunctionLiteralKind,
1419-
arguments: &'ast [TypedArg],
1420-
body: &'ast Vec1<TypedStatement>,
1421-
return_annotation: &'ast Option<ast::TypeAst>,
1422-
) {
1423-
for argument in arguments {
1424-
if let Some(annotation) = &argument.annotation {
1425-
self.visit_type_ast(annotation);
1426-
}
1427-
}
1428-
if let Some(return_) = return_annotation {
1429-
self.visit_type_ast(return_);
1430-
}
1431-
ast::visit::visit_typed_expr_fn(
1432-
self,
1433-
location,
1434-
type_,
1435-
kind,
1436-
arguments,
1437-
body,
1438-
return_annotation,
1439-
);
1440-
}
1441-
14421426
fn visit_type_ast_constructor(
14431427
&mut self,
14441428
location: &'ast SrcSpan,
@@ -1637,34 +1621,6 @@ impl<'a> QualifiedToUnqualifiedImportSecondPass<'a> {
16371621
}
16381622

16391623
impl<'ast> ast::visit::Visit<'ast> for QualifiedToUnqualifiedImportSecondPass<'ast> {
1640-
fn visit_typed_expr_fn(
1641-
&mut self,
1642-
location: &'ast SrcSpan,
1643-
type_: &'ast Arc<Type>,
1644-
kind: &'ast FunctionLiteralKind,
1645-
arguments: &'ast [TypedArg],
1646-
body: &'ast Vec1<TypedStatement>,
1647-
return_annotation: &'ast Option<ast::TypeAst>,
1648-
) {
1649-
for argument in arguments {
1650-
if let Some(annotation) = &argument.annotation {
1651-
self.visit_type_ast(annotation);
1652-
}
1653-
}
1654-
if let Some(return_) = return_annotation {
1655-
self.visit_type_ast(return_);
1656-
}
1657-
ast::visit::visit_typed_expr_fn(
1658-
self,
1659-
location,
1660-
type_,
1661-
kind,
1662-
arguments,
1663-
body,
1664-
return_annotation,
1665-
);
1666-
}
1667-
16681624
fn visit_type_ast_constructor(
16691625
&mut self,
16701626
location: &'ast SrcSpan,
@@ -1869,34 +1825,6 @@ impl<'a> UnqualifiedToQualifiedImportFirstPass<'a> {
18691825
}
18701826

18711827
impl<'ast> ast::visit::Visit<'ast> for UnqualifiedToQualifiedImportFirstPass<'ast> {
1872-
fn visit_typed_expr_fn(
1873-
&mut self,
1874-
location: &'ast SrcSpan,
1875-
type_: &'ast Arc<Type>,
1876-
kind: &'ast FunctionLiteralKind,
1877-
arguments: &'ast [TypedArg],
1878-
body: &'ast Vec1<TypedStatement>,
1879-
return_annotation: &'ast Option<ast::TypeAst>,
1880-
) {
1881-
for argument in arguments {
1882-
if let Some(annotation) = &argument.annotation {
1883-
self.visit_type_ast(annotation);
1884-
}
1885-
}
1886-
if let Some(return_) = return_annotation {
1887-
self.visit_type_ast(return_);
1888-
}
1889-
ast::visit::visit_typed_expr_fn(
1890-
self,
1891-
location,
1892-
type_,
1893-
kind,
1894-
arguments,
1895-
body,
1896-
return_annotation,
1897-
);
1898-
}
1899-
19001828
fn visit_type_ast_constructor(
19011829
&mut self,
19021830
location: &'ast SrcSpan,
@@ -2073,47 +2001,6 @@ impl<'a> UnqualifiedToQualifiedImportSecondPass<'a> {
20732001
}
20742002

20752003
impl<'ast> ast::visit::Visit<'ast> for UnqualifiedToQualifiedImportSecondPass<'ast> {
2076-
fn visit_typed_expr_fn(
2077-
&mut self,
2078-
location: &'ast SrcSpan,
2079-
type_: &'ast Arc<Type>,
2080-
kind: &'ast FunctionLiteralKind,
2081-
arguments: &'ast [TypedArg],
2082-
body: &'ast Vec1<TypedStatement>,
2083-
return_annotation: &'ast Option<ast::TypeAst>,
2084-
) {
2085-
for argument in arguments {
2086-
if let Some(annotation) = &argument.annotation {
2087-
self.visit_type_ast(annotation);
2088-
}
2089-
}
2090-
if let Some(return_) = return_annotation {
2091-
self.visit_type_ast(return_);
2092-
}
2093-
ast::visit::visit_typed_expr_fn(
2094-
self,
2095-
location,
2096-
type_,
2097-
kind,
2098-
arguments,
2099-
body,
2100-
return_annotation,
2101-
);
2102-
}
2103-
2104-
fn visit_typed_function(&mut self, fun: &'ast ast::TypedFunction) {
2105-
for arg in &fun.arguments {
2106-
if let Some(annotation) = &arg.annotation {
2107-
self.visit_type_ast(annotation);
2108-
}
2109-
}
2110-
2111-
if let Some(return_annotation) = &fun.return_annotation {
2112-
self.visit_type_ast(return_annotation);
2113-
}
2114-
ast::visit::visit_typed_function(self, fun);
2115-
}
2116-
21172004
fn visit_type_ast_constructor(
21182005
&mut self,
21192006
location: &'ast SrcSpan,

compiler-core/src/language_server/tests/action.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9508,3 +9508,19 @@ fn many_args(a, b, c, d: d, e: a, f, g) {
95089508
find_position_of("many_args").to_selection()
95099509
);
95109510
}
9511+
9512+
#[test]
9513+
fn type_variables_in_let_bindings_are_considered_when_adding_annotations() {
9514+
assert_code_action!(
9515+
ADD_ANNOTATIONS,
9516+
"
9517+
fn wibble(a, b, c) {
9518+
let x: a = todo
9519+
fn(a: b, b: c) -> d {
9520+
todo
9521+
}
9522+
}
9523+
",
9524+
find_position_of("wibble").to_selection()
9525+
);
9526+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
source: compiler-core/src/language_server/tests/action.rs
3+
expression: "\nfn wibble(a, b, c) {\n let x: a = todo\n fn(a: b, b: c) -> d {\n todo\n }\n}\n"
4+
---
5+
----- BEFORE ACTION
6+
7+
fn wibble(a, b, c) {
8+
9+
let x: a = todo
10+
fn(a: b, b: c) -> d {
11+
todo
12+
}
13+
}
14+
15+
16+
----- AFTER ACTION
17+
18+
fn wibble(a: e, b: f, c: g) -> fn(b, c) -> d {
19+
let x: a = todo
20+
fn(a: b, b: c) -> d {
21+
todo
22+
}
23+
}

0 commit comments

Comments
 (0)