aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.md2
-rw-r--r--src/compile/assignments.c6
-rw-r--r--src/compile/promotions.c6
-rw-r--r--test/pointers.tm13
4 files changed, 22 insertions, 5 deletions
diff --git a/CHANGES.md b/CHANGES.md
index 096457bd..1e1e56d7 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -50,6 +50,8 @@
resources, which could lead to exhausting the number of open file handles.
When that happens, the standard library now forces a GC collection to clean
up resources, which can result in file handles being freed up.
+ - `&` references failed to propagate when accessing fields like
+ `foo.baz.method()` when `foo` is a `&Foo` and `baz.method()` takes a `&Baz`.
## v0.3
diff --git a/src/compile/assignments.c b/src/compile/assignments.c
index 74d1b543..c0f45f5b 100644
--- a/src/compile/assignments.c
+++ b/src/compile/assignments.c
@@ -183,9 +183,9 @@ Text_t compile_lvalue(env_t *env, ast_t *ast) {
compile_type_info(container_t), ")");
}
return Texts("*(", compile_type(Type(PointerType, table_type->value_type)), ")Table$reserve(",
- compile_to_pointer_depth(env, index->indexed, 1, false), ", ",
- compile_to_type(env, index->index, Type(PointerType, table_type->key_type, .is_stack = true)),
- ", NULL,", compile_type_info(container_t), ")");
+ compile_to_pointer_depth(env, index->indexed, 1, false), ", ", "stack(",
+ compile_to_type(env, index->index, table_type->key_type), ")", ", NULL,",
+ compile_type_info(container_t), ")");
} else {
code_err(ast, "I don't know how to assign to this target");
}
diff --git a/src/compile/promotions.c b/src/compile/promotions.c
index 68b4f64c..b3cbb361 100644
--- a/src/compile/promotions.c
+++ b/src/compile/promotions.c
@@ -182,8 +182,10 @@ Text_t compile_to_type(env_t *env, ast_t *ast, type_t *t) {
}
// Promote values to views-of-values if needed:
- if (t->tag == PointerType && Match(t, PointerType)->is_stack && actual->tag != PointerType)
- return Texts("stack(", compile_to_type(env, ast, Match(t, PointerType)->pointed), ")");
+ if (t->tag == PointerType && Match(t, PointerType)->is_stack && actual->tag != PointerType) {
+ if (type_eq(actual, Match(t, PointerType)->pointed) && can_be_mutated(env, ast))
+ return Texts("&(", compile_lvalue(env, ast), ")");
+ }
if (!is_incomplete_type(actual)) {
Text_t code = compile(env, ast);
diff --git a/test/pointers.tm b/test/pointers.tm
new file mode 100644
index 00000000..9834044c
--- /dev/null
+++ b/test/pointers.tm
@@ -0,0 +1,13 @@
+struct Foo(x:Int)
+ func update(f:&Foo)
+ f.x += 1
+
+struct Baz(foo:Foo)
+ func update(b:&Baz)
+ # Make sure & propagates here!
+ b.foo.update()
+
+func main()
+ b := Baz(Foo(123))
+ b.update()
+ assert b.foo.x == 124