about summary refs log tree commit diff stats
path: root/056recipe_header.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-01-23 14:13:32 -0800
committerKartik K. Agaram <vc@akkartik.com>2016-01-23 14:16:48 -0800
commitee67a3417802a66e2d8741536dedf99baf78cc5a (patch)
tree86560ac5e7da6b461b2dd16b5b4b7fdd67843aa2 /056recipe_header.cc
parentcf478e14aab32fbfcccd7443e6b2de4f2c247060 (diff)
downloadmu-ee67a3417802a66e2d8741536dedf99baf78cc5a.tar.gz
2596 - experiment: no unique addresses in calls
Reading http://www.jonathanturner.org/2016/01/rust-and-blub-paradox.html,
I realize there's nothing currently stopping mu programs from taking a
unique (non-shared) address into a shared allocation, abandoning the
allocation and being left with an invalid address. No fix for this yet,
but let's try to minimize its effect by limiting lifetimes of unique
addresses. We really should only be using them to write to array or
container elements.
Diffstat (limited to '056recipe_header.cc')
-rw-r--r--056recipe_header.cc38
1 files changed, 38 insertions, 0 deletions
diff --git a/056recipe_header.cc b/056recipe_header.cc
index 026f44e6..df4ebdc9 100644
--- a/056recipe_header.cc
+++ b/056recipe_header.cc
@@ -218,15 +218,53 @@ void check_calls_against_header(const recipe_ordinal r) {
     for (long int i = 0; i < min(SIZE(inst.ingredients), SIZE(callee.ingredients)); ++i) {
       if (!types_coercible(callee.ingredients.at(i), inst.ingredients.at(i)))
         raise_error << maybe(caller.name) << "ingredient " << i << " has the wrong type at '" << inst.to_string() << "'\n" << end();
+      if (is_unique_address(inst.ingredients.at(i)))
+        raise << maybe(caller.name) << "try to avoid passing non-shared addresses into calls, like ingredient " << i << " at '" << inst.to_string() << "'\n" << end();
     }
     for (long int i = 0; i < min(SIZE(inst.products), SIZE(callee.products)); ++i) {
       if (is_dummy(inst.products.at(i))) continue;
       if (!types_coercible(callee.products.at(i), inst.products.at(i)))
         raise_error << maybe(caller.name) << "product " << i << " has the wrong type at '" << inst.to_string() << "'\n" << end();
+      if (is_unique_address(inst.products.at(i)))
+        raise << maybe(caller.name) << "try to avoid getting non-shared addresses out of calls, like product " << i << " at '" << inst.to_string() << "'\n" << end();
     }
   }
 }
 
+bool is_unique_address(reagent x) {
+  if (!canonize_type(x)) return false;
+  if (!x.type) return false;
+  if (x.type->value != get(Type_ordinal, "address")) return false;
+  if (!x.type->right) return true;
+  return x.type->right->value != get(Type_ordinal, "shared");
+}
+
+//: additionally, warn on calls receiving non-shared addresses
+
+:(scenario warn_on_calls_with_addresses)
+% Hide_warnings= true;
+recipe main [
+  1:address:number <- copy 3/unsafe
+  foo 1:address:number
+]
+recipe foo x:address:number [
+  local-scope
+  load-ingredients
+]
++warn: main: try to avoid passing non-shared addresses into calls, like ingredient 0 at 'foo 1:address:number'
+
+:(scenario warn_on_calls_with_addresses_2)
+% Hide_warnings= true;
+recipe main [
+  1:address:number <- foo
+]
+recipe foo -> x:address:number [
+  local-scope
+  load-ingredients
+  x <- copy 0
+]
++warn: main: try to avoid getting non-shared addresses out of calls, like product 0 at '1:address:number <- foo '
+
 //:: Check types going in and out of all recipes with headers.
 
 :(scenarios transform)