Commit 0ff9a4d21c

Andrew Kelley <andrew@ziglang.org>
2021-07-05 23:07:36
stage1: resolve lazy values before comptime fn call
1 parent 0e5fa87
Changed files (3)
src/stage1/analyze.cpp
@@ -5674,7 +5674,7 @@ static uint32_t hash_combine_const_val(uint32_t hash_val, ZigValue *const_val) {
     //     return hash_combine(hash_val, &const_val);
     // }
     if (const_val->special != ConstValSpecialStatic) {
-        printf("\nInvalid special: %d\n", const_val->special);
+        fprintf(stderr, "\nInvalid special: %d\n", const_val->special);
     }
     assert(const_val->special == ConstValSpecialStatic);
     hash_val = hash_combine(hash_val, &const_val->type->id);
@@ -5776,9 +5776,6 @@ static uint32_t hash_combine_const_val(uint32_t hash_val, ZigValue *const_val) {
     }
     zig_unreachable();
 }
-static uint32_t hash_const_val(ZigValue *const_val) {
-    return hash_combine_const_val(HASH_INIT, const_val);
-}
 
 uint32_t generic_fn_type_id_hash(GenericFnTypeId *id) {
     uint32_t result = HASH_INIT;
src/stage1/ir.cpp
@@ -12754,6 +12754,29 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, Scope *scope, AstNode *sour
         bool cacheable = fn_eval_cacheable(exec_scope, return_type);
         ZigValue *result = nullptr;
         if (cacheable) {
+            // We are about to put ZigValues into a hash map. The hash of a lazy value and a
+            // fully resolved value must equal, and so we must resolve the lazy values here.
+            // The hash function asserts that none of the values are lazy.
+            {
+                Scope *scope = exec_scope;
+                while (scope) {
+                    if (scope->id == ScopeIdVarDecl) {
+                        ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
+                        if ((err = ir_resolve_lazy_recurse(ira,
+                            var_scope->var->decl_node,
+                            var_scope->var->const_value)))
+                        {
+                            return ira->codegen->invalid_inst_gen;
+                        }
+                    } else if (scope->id == ScopeIdFnDef) {
+                        break;
+                    } else {
+                        zig_unreachable();
+                    }
+                    scope = scope->parent;
+                }
+            }
+
             auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope);
             if (entry)
                 result = entry->value;
@@ -25558,7 +25581,7 @@ static Error ir_resolve_lazy_recurse(IrAnalyze *ira, AstNode *source_node, ZigVa
         // This shouldn't be possible, it indicates an ICE.
         // NO_COMMIT
         ir_add_error_node(ira, source_node,
-            buf_sprintf("This is a bug in the Zig compiler. Runtime value found in comptime known parameter."));
+            buf_sprintf("This is a bug in the Zig compiler. Runtime value found in comptime known value."));
         return ErrorSemanticAnalyzeFail;
     }
     if (val->special != ConstValSpecialStatic)
src/stage1/zig0.cpp
@@ -265,6 +265,7 @@ int main(int argc, char **argv) {
     const char *override_lib_dir = nullptr;
     const char *mcpu = nullptr;
     bool single_threaded = false;
+    bool is_test_build = false;
 
     for (int i = 1; i < argc; i += 1) {
         char *arg = argv[i];
@@ -272,6 +273,8 @@ int main(int argc, char **argv) {
         if (arg[0] == '-') {
             if (strcmp(arg, "--") == 0) {
                 fprintf(stderr, "Unexpected end-of-parameter mark: %s\n", arg);
+            } else if (strcmp(arg, "--test") == 0) {
+                is_test_build = true;
             } else if (strcmp(arg, "-ODebug") == 0) {
                 optimize_mode = BuildModeDebug;
             } else if (strcmp(arg, "-OReleaseFast") == 0) {
@@ -446,7 +449,7 @@ int main(int argc, char **argv) {
         nullptr, 0,
         in_file, strlen(in_file),
         override_lib_dir, strlen(override_lib_dir),
-        &target, false);
+        &target, is_test_build);
 
     stage1->main_progress_node = root_progress_node;
     stage1->root_name_ptr = out_name;