Skip to content

Commit 4ffbca8

Browse files
committed
fix(parser): preserve map iterator schemas
1 parent e918439 commit 4ffbca8

2 files changed

Lines changed: 22 additions & 10 deletions

File tree

src/compiler/parser/statements.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,11 +1241,21 @@ impl Parser {
12411241

12421242
let previous_key_slot = self.replace_current_local_binding(&key_name, key_slot);
12431243
let previous_value_slot = self.replace_current_local_binding(&value_name, value_slot);
1244+
let previous_key_schema = self.local_schemas.get(&key_slot).cloned();
1245+
let previous_value_schema = self.local_schemas.get(&value_slot).cloned();
1246+
if let Some(schema) = key_schema.as_ref() {
1247+
self.local_schemas.insert(key_slot, schema.clone());
1248+
}
1249+
if let Some(schema) = value_schema.as_ref() {
1250+
self.local_schemas.insert(value_slot, schema.clone());
1251+
}
12441252
self.borrowed_map_iter_locals.push(map_slot);
12451253
self.loop_depth += 1;
12461254
let body_result = self.parse_block("expected '{' after borrowed map");
12471255
self.loop_depth -= 1;
12481256
self.borrowed_map_iter_locals.pop();
1257+
self.restore_local_schema(value_slot, previous_value_schema);
1258+
self.restore_local_schema(key_slot, previous_key_schema);
12491259
self.restore_current_local_binding(&value_name, previous_value_slot);
12501260
self.restore_current_local_binding(&key_name, previous_key_slot);
12511261
let mut body = body_result?;
@@ -1328,6 +1338,14 @@ impl Parser {
13281338
}
13291339
}
13301340

1341+
fn restore_local_schema(&mut self, slot: LocalSlot, previous: Option<TypeSchema>) {
1342+
if let Some(schema) = previous {
1343+
self.local_schemas.insert(slot, schema);
1344+
} else {
1345+
self.local_schemas.remove(&slot);
1346+
}
1347+
}
1348+
13311349
fn bind_for_loop_local(&mut self, name: &str) -> Result<(LocalSlot, bool), ParseError> {
13321350
if !self.closure_scopes.is_empty() {
13331351
if let Some(index) = self

tests/example_tests.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -387,12 +387,10 @@ fn rustscript_untyped_rebinding_does_not_reuse_stale_map_schema() {
387387
let source = r#"
388388
let values: map<int> = {a: 1};
389389
let values = {a: "x"};
390-
for (key: string, value: int) in &values {
391-
value;
392-
}
390+
for (key: string, value: int) in &values { value; }
393391
"#;
394392
let err = match compile_source_with_flavor(source, SourceFlavor::RustScript) {
395-
Ok(_) => panic!("untyped rebinding must not retain the old map<int> schema"),
393+
Ok(_) => panic!("untyped rebinding must clear stale map schema"),
396394
Err(err) => err,
397395
};
398396
assert!(err.to_string().contains("map<T> schema"));
@@ -403,9 +401,7 @@ fn rustscript_function_parameter_map_type_is_visible_to_iterators() {
403401
let source = r#"
404402
fn sum(values: map<int>) -> int {
405403
let mut total: int = 0;
406-
for (key: string, value: int) in &values {
407-
total += value;
408-
}
404+
for (key: string, value: int) in &values { total += value; }
409405
total
410406
}
411407
sum({a: 1, b: 2});
@@ -422,9 +418,7 @@ fn rustscript_borrowed_map_iterator_propagates_nested_binding_schema() {
422418
let groups: map<map<int>> = {first: {a: 1, b: 2}};
423419
let mut total: int = 0;
424420
for (group_key: string, group: map<int>) in &groups {
425-
for (item_key: string, item: int) in &group {
426-
total += item;
427-
}
421+
for (item_key: string, item: int) in &group { total += item; }
428422
}
429423
total;
430424
"#;

0 commit comments

Comments
 (0)