about summary refs log tree commit diff stats
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
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.
-rw-r--r--056recipe_header.cc38
-rw-r--r--059shape_shifting_recipe.cc6
2 files changed, 41 insertions, 3 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)
diff --git a/059shape_shifting_recipe.cc b/059shape_shifting_recipe.cc
index 3811dd36..97bd8dfe 100644
--- a/059shape_shifting_recipe.cc
+++ b/059shape_shifting_recipe.cc
@@ -591,13 +591,13 @@ recipe bar a:_t -> result:_t [
 % Hide_errors = true;
 recipe main [
   a:number <- copy 3
-  b:address:number <- foo a
+  b:address:shared:number <- foo a
 ]
 recipe foo a:_t -> b:_t [
   load-ingredients
   b <- copy a
 ]
-+error: main: no call found for 'b:address:number <- foo a'
++error: main: no call found for 'b:address:shared:number <- foo a'
 
 :(scenario specialize_inside_recipe_without_header)
 recipe main [
@@ -646,7 +646,7 @@ recipe foo x:_elem -> y:_elem [
 recipe main [
   local-scope
   # permit '0' to map to address to shape-shifting type-ingredient
-  1:address:character/raw <- foo 0
+  1:address:shared:character/raw <- foo 0
 ]
 recipe foo x:address:_elem -> y:address:_elem [
   local-scope