Commit 31d8efc6b3

Vexu <git@vexu.eu>
2020-08-18 12:57:09
stage2: validate param and variable types
1 parent 7c15c94
Changed files (2)
src-self-hosted
src-self-hosted/type.zig
@@ -1062,6 +1062,45 @@ pub const Type = extern union {
         }
     }
 
+    /// Returns if type can be used for a runtime variable
+    pub fn isValidVarType(self: Type) bool {
+        var ty = self;
+        while (true) switch (ty.zigTypeTag()) {
+            .Bool,
+            .Int,
+            .Float,
+            .ErrorSet,
+            .Enum,
+            .Frame,
+            .AnyFrame,
+            .Vector,
+            => return true,
+
+            .BoundFn,
+            .ComptimeFloat,
+            .ComptimeInt,
+            .EnumLiteral,
+            .NoReturn,
+            .Type,
+            .Void,
+            .Undefined,
+            .Null,
+            .Opaque,
+            => return false,
+
+            .Optional => {
+                var buf: Payload.Pointer = undefined;
+                return ty.optionalChild(&buf).isValidVarType();
+            },
+            .Pointer, .Array => ty = ty.elemType(),
+
+            .ErrorUnion => @panic("TODO fn isValidVarType"),
+            .Fn => @panic("TODO fn isValidVarType"),
+            .Struct => @panic("TODO struct isValidVarType"),
+            .Union => @panic("TODO union isValidVarType"),
+        };
+    }
+
     /// Asserts the type is a pointer or array type.
     pub fn elemType(self: Type) Type {
         return switch (self.tag()) {
src-self-hosted/zir_sema.zig
@@ -364,6 +364,9 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst.
 
 fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
     const var_type = try resolveType(mod, scope, inst.positionals.operand);
+    if (!var_type.isValidVarType()) {
+        return mod.fail(scope, inst.base.src, "variable of type '{}' must be const or comptime", .{var_type});
+    }
     const ptr_type = try mod.singlePtrType(scope, inst.base.src, true, var_type);
     const b = try mod.requireRuntimeBlock(scope, inst.base.src);
     return mod.addNoOp(b, inst.base.src, ptr_type, .alloc);
@@ -760,7 +763,12 @@ fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inne
     const arena = scope.arena();
     const param_types = try arena.alloc(Type, fntype.positionals.param_types.len);
     for (fntype.positionals.param_types) |param_type, i| {
-        param_types[i] = try resolveType(mod, scope, param_type);
+        const resolved = try resolveType(mod, scope, param_type);
+        // TODO skip for comptime params
+        if (!resolved.isValidVarType()) {
+            return mod.fail(scope, param_type.src, "parameter of type '{}' must be declared comptime", .{resolved});
+        }
+        param_types[i] = resolved;
     }
 
     const payload = try arena.create(Type.Payload.Function);