about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--059shape_shifting_recipe.cc40
1 files changed, 28 insertions, 12 deletions
diff --git a/059shape_shifting_recipe.cc b/059shape_shifting_recipe.cc
index 7b2d547d..2436b924 100644
--- a/059shape_shifting_recipe.cc
+++ b/059shape_shifting_recipe.cc
@@ -163,7 +163,7 @@ recipe_ordinal new_variant(recipe_ordinal exemplar, const instruction& inst, con
       delete p->second;
     if (error) return exemplar;
   }
-  ensure_all_concrete_types(new_recipe);
+  ensure_all_concrete_types(new_recipe, get(Recipe, exemplar));
   // finally, perform all transforms on the new specialization
   for (long long int t = 0; t < SIZE(Transform); ++t) {
     (*Transform.at(t))(new_recipe_ordinal);
@@ -320,27 +320,28 @@ void replace_type_ingredients(string_tree* type, const map<string, const string_
   replace_type_ingredients(type->right, mappings);
 }
 
-void ensure_all_concrete_types(const recipe& new_recipe) {
+void ensure_all_concrete_types(/*const*/ recipe& new_recipe, const recipe& exemplar) {
   for (long long int i = 0; i < SIZE(new_recipe.ingredients); ++i)
-    ensure_all_concrete_types(new_recipe.ingredients.at(i).type);
+    ensure_all_concrete_types(new_recipe.ingredients.at(i), exemplar);
   for (long long int i = 0; i < SIZE(new_recipe.products); ++i)
-    ensure_all_concrete_types(new_recipe.products.at(i).type);
+    ensure_all_concrete_types(new_recipe.products.at(i), exemplar);
   for (long long int i = 0; i < SIZE(new_recipe.steps); ++i) {
-    const instruction& inst = new_recipe.steps.at(i);
+    instruction& inst = new_recipe.steps.at(i);
     for (long long int j = 0; j < SIZE(inst.ingredients); ++j)
-      ensure_all_concrete_types(inst.ingredients.at(j).type);
+      ensure_all_concrete_types(inst.ingredients.at(j), exemplar);
     for (long long int j = 0; j < SIZE(inst.products); ++j)
-      ensure_all_concrete_types(inst.products.at(j).type);
+      ensure_all_concrete_types(inst.products.at(j), exemplar);
   }
 }
 
-void ensure_all_concrete_types(const type_tree* x) {
-  if (!x) {
-    raise << "null type\n" << end();
+void ensure_all_concrete_types(/*const*/ reagent& x, const recipe& exemplar) {
+  if (!x.type) {
+    raise_error << maybe(exemplar.name) << "failed to map a type to " << x.original_string << '\n' << end();
+    x.type = new type_tree(0);  // just to prevent crashes later
     return;
   }
-  if (x->value == -1) {
-    raise << "unknown type\n" << end();
+  if (x.type->value == -1) {
+    raise_error << maybe(exemplar.name) << "failed to map a type to the unknown " << x.original_string << '\n' << end();
     return;
   }
 }
@@ -523,3 +524,18 @@ recipe foo x:address:_elem -> y:address:_elem [
 ]
 +mem: storing 0 in location 1
 $error: 0
+
+:(scenario specialize_with_literal_4)
+% Hide_errors = true;
+recipe main [
+  local-scope
+  # ambiguous call: what's the type of its ingredient?!
+  foo 0
+]
+recipe foo x:address:_elem -> y:address:_elem [
+  local-scope
+  load-ingredients
+  y <- copy x
+]
++error: foo: failed to map a type to x
++error: foo: failed to map a type to y