Commit 63f636e7b7

Andrew Kelley <superjoe30@gmail.com>
2018-11-06 17:09:14
limit integer types to maximum bit width of 65535
closes #1541
1 parent a08b657
doc/langref.html.in
@@ -8,6 +8,7 @@
       body{
         background-color:#111;
         color: #bbb;
+        font-family: sans-serif;
       }
       a {
         color: #88f;
@@ -467,9 +468,10 @@ pub fn main() void {
       <p>
       In addition to the integer types above, arbitrary bit-width integers can be referenced by using
       an identifier of <code>i</code> or </code>u</code> followed by digits. For example, the identifier
-      {#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer.
+      {#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an
+      integer type is {#syntax#}65535{#endsyntax#}.
       </p>
-      {#see_also|Integers|Floats|void|Errors#}
+      {#see_also|Integers|Floats|void|Errors|@IntType#}
       {#header_close#}
       {#header_open|Primitive Values#}
       <div class="table-wrapper">
@@ -5814,9 +5816,10 @@ fn add(a: i32, b: i32) i32 { return a + b; }
       {#header_close#}
 
       {#header_open|@IntType#}
-      <pre>{#syntax#}@IntType(comptime is_signed: bool, comptime bit_count: u32) type{#endsyntax#}</pre>
+      <pre>{#syntax#}@IntType(comptime is_signed: bool, comptime bit_count: u16) type{#endsyntax#}</pre>
       <p>
-      This function returns an integer type with the given signness and bit count.
+      This function returns an integer type with the given signness and bit count. The maximum
+      bit count for an integer type is {#syntax#}65535{#endsyntax#}.
       </p>
       {#header_close#}
       {#header_open|@memberCount#}
src/all_types.hpp
@@ -1222,7 +1222,6 @@ struct ZigType {
     ZigLLVMDIType *di_type;
 
     bool zero_bits; // this is denormalized data
-    bool is_copyable;
     bool gen_h_loop_flag;
 
     union {
src/analyze.cpp
@@ -367,23 +367,6 @@ uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) {
     return LLVMSizeOfTypeInBits(g->target_data_ref, type_entry->type_ref);
 }
 
-Result<bool> type_is_copyable(CodeGen *g, ZigType *type_entry) {
-    Error err;
-    if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
-        return err;
-
-    if (!type_has_bits(type_entry))
-        return true;
-
-    if (!handle_is_ptr(type_entry))
-        return true;
-
-    if ((err = ensure_complete_type(g, type_entry)))
-        return err;
-
-    return type_entry->is_copyable;
-}
-
 static bool is_slice(ZigType *type) {
     return type->id == ZigTypeIdStruct && type->data.structure.is_slice;
 }
@@ -465,7 +448,6 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
     assert(type_is_resolved(child_type, ResolveStatusZeroBitsKnown));
 
     ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
-    entry->is_copyable = true;
 
     const char *star_str = ptr_len == PtrLenSingle ? "*" : "[*]";
     const char *const_str = is_const ? "const " : "";
@@ -581,7 +563,6 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
 
         ZigType *entry = new_type_table_entry(ZigTypeIdOptional);
         assert(child_type->type_ref || child_type->zero_bits);
-        entry->is_copyable = type_is_copyable(g, child_type).unwrap();
 
         buf_resize(&entry->name, 0);
         buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name));
@@ -671,7 +652,6 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa
     }
 
     ZigType *entry = new_type_table_entry(ZigTypeIdErrorUnion);
-    entry->is_copyable = true;
     assert(payload_type->di_type);
     assert(type_is_complete(payload_type));
 
@@ -766,7 +746,6 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) {
 
     ZigType *entry = new_type_table_entry(ZigTypeIdArray);
     entry->zero_bits = (array_size == 0) || child_type->zero_bits;
-    entry->is_copyable = false;
 
     buf_resize(&entry->name, 0);
     buf_appendf(&entry->name, "[%" ZIG_PRI_u64 "]%s", array_size, buf_ptr(&child_type->name));
@@ -831,7 +810,6 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
     }
 
     ZigType *entry = new_type_table_entry(ZigTypeIdStruct);
-    entry->is_copyable = true;
 
     // replace the & with [] to go from a ptr type name to a slice type name
     buf_resize(&entry->name, 0);
@@ -986,7 +964,6 @@ ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const c
     ImportTableEntry *import = scope ? get_scope_import(scope) : nullptr;
     unsigned line = source_node ? (unsigned)(source_node->line + 1) : 0;
 
-    entry->is_copyable = false;
     entry->type_ref = LLVMInt8Type();
     entry->di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder,
         ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name),
@@ -1005,7 +982,6 @@ ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry) {
         return fn_type->data.fn.bound_fn_parent;
 
     ZigType *bound_fn_type = new_type_table_entry(ZigTypeIdBoundFn);
-    bound_fn_type->is_copyable = false;
     bound_fn_type->data.bound_fn.fn_type = fn_type;
     bound_fn_type->zero_bits = true;
 
@@ -1105,7 +1081,6 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
     }
 
     ZigType *fn_type = new_type_table_entry(ZigTypeIdFn);
-    fn_type->is_copyable = true;
     fn_type->data.fn.fn_type_id = *fn_type_id;
 
     bool skip_debug_info = false;
@@ -1318,7 +1293,6 @@ ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
 
 ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
     ZigType *fn_type = new_type_table_entry(ZigTypeIdFn);
-    fn_type->is_copyable = false;
     buf_resize(&fn_type->name, 0);
     if (fn_type->data.fn.fn_type_id.cc == CallingConventionAsync) {
         const char *async_allocator_type_str = (fn_type->data.fn.fn_type_id.async_allocator_type == nullptr) ?
@@ -1526,7 +1500,6 @@ ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry) {
     ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
     buf_resize(&err_set_type->name, 0);
     buf_appendf(&err_set_type->name, "@typeOf(%s).ReturnType.ErrorSet", buf_ptr(&fn_entry->symbol_name));
-    err_set_type->is_copyable = true;
     err_set_type->type_ref = g->builtin_types.entry_global_error_set->type_ref;
     err_set_type->di_type = g->builtin_types.entry_global_error_set->di_type;
     err_set_type->data.error_set.err_count = 0;
@@ -2846,7 +2819,6 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
         tag_type = new_type_table_entry(ZigTypeIdEnum);
         buf_resize(&tag_type->name, 0);
         buf_appendf(&tag_type->name, "@TagType(%s)", buf_ptr(&union_type->name));
-        tag_type->is_copyable = true;
         tag_type->type_ref = tag_int_type->type_ref;
         tag_type->zero_bits = tag_int_type->zero_bits;
 
@@ -3366,10 +3338,10 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
     }
 
     {
-        ZigType *type = get_primitive_type(g, tld->name);
-        if (type != nullptr) {
+        ZigType *type;
+        if (get_primitive_type(g, tld->name, &type) != ErrorPrimitiveTypeNotFound) {
             add_node_error(g, tld->source_node,
-                    buf_sprintf("declaration shadows type '%s'", buf_ptr(&type->name)));
+                buf_sprintf("declaration shadows primitive type '%s'", buf_ptr(tld->name)));
         }
     }
 }
@@ -3613,10 +3585,10 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
             add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
             variable_entry->value->type = g->builtin_types.entry_invalid;
         } else {
-            ZigType *type = get_primitive_type(g, name);
-            if (type != nullptr) {
+            ZigType *type;
+            if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {
                 add_node_error(g, source_node,
-                        buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));
+                        buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
                 variable_entry->value->type = g->builtin_types.entry_invalid;
             } else {
                 Scope *search_scope = nullptr;
@@ -4435,6 +4407,7 @@ void semantic_analyze(CodeGen *g) {
 }
 
 ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
+    assert(size_in_bits <= 65535);
     TypeId type_id = {};
     type_id.id = ZigTypeIdInt;
     type_id.data.integer.is_signed = is_signed;
@@ -4523,7 +4496,7 @@ Buf *get_linux_libc_lib_path(const char *o_file) {
     Termination term;
     Buf *out_stderr = buf_alloc();
     Buf *out_stdout = buf_alloc();
-    int err;
+    Error err;
     if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
         zig_panic("unable to determine libc lib path: executing C compiler: %s", err_str(err));
     }
@@ -4552,7 +4525,7 @@ Buf *get_linux_libc_include_path(void) {
     Termination term;
     Buf *out_stderr = buf_alloc();
     Buf *out_stdout = buf_alloc();
-    int err;
+    Error err;
     if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
         zig_panic("unable to determine libc include path: executing C compiler: %s", err_str(err));
     }
@@ -5977,8 +5950,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
 }
 
 ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
+    assert(size_in_bits <= 65535);
     ZigType *entry = new_type_table_entry(ZigTypeIdInt);
-    entry->is_copyable = true;
     entry->type_ref = (size_in_bits == 0) ? LLVMVoidType() : LLVMIntType(size_in_bits);
     entry->zero_bits = (size_in_bits == 0);
 
@@ -6455,7 +6428,10 @@ bool fn_type_can_fail(FnTypeId *fn_type_id) {
     return type_can_fail(fn_type_id->return_type) || fn_type_id->cc == CallingConventionAsync;
 }
 
-ZigType *get_primitive_type(CodeGen *g, Buf *name) {
+// ErrorNone - result pointer has the type
+// ErrorOverflow - an integer primitive type has too large a bit width
+// ErrorPrimitiveTypeNotFound - result pointer unchanged
+Error get_primitive_type(CodeGen *g, Buf *name, ZigType **result) {
     if (buf_len(name) >= 2) {
         uint8_t first_c = buf_ptr(name)[0];
         if (first_c == 'i' || first_c == 'u') {
@@ -6466,18 +6442,22 @@ ZigType *get_primitive_type(CodeGen *g, Buf *name) {
                 }
             }
             bool is_signed = (first_c == 'i');
-            uint32_t bit_count = atoi(buf_ptr(name) + 1);
-            return get_int_type(g, is_signed, bit_count);
+            unsigned long int bit_count = strtoul(buf_ptr(name) + 1, nullptr, 10);
+            // strtoul returns ULONG_MAX on errors, so this comparison catches that as well.
+            if (bit_count >= 65536) return ErrorOverflow;
+            *result = get_int_type(g, is_signed, bit_count);
+            return ErrorNone;
         }
     }
 
 not_integer:
 
     auto primitive_table_entry = g->primitive_type_table.maybe_get(name);
-    if (primitive_table_entry != nullptr) {
-        return primitive_table_entry->value;
-    }
-    return nullptr;
+    if (primitive_table_entry == nullptr)
+        return ErrorPrimitiveTypeNotFound;
+
+    *result = primitive_table_entry->value;
+    return ErrorNone;
 }
 
 Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents) {
src/analyze.hpp
@@ -9,7 +9,6 @@
 #define ZIG_ANALYZE_HPP
 
 #include "all_types.hpp"
-#include "result.hpp"
 
 void semantic_analyze(CodeGen *g);
 ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);
@@ -180,7 +179,6 @@ ZigTypeId type_id_at_index(size_t index);
 size_t type_id_len();
 size_t type_id_index(ZigType *entry);
 ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id);
-Result<bool> type_is_copyable(CodeGen *g, ZigType *type_entry);
 LinkLib *create_link_lib(Buf *name);
 LinkLib *add_link_lib(CodeGen *codegen, Buf *lib);
 
@@ -204,7 +202,7 @@ bool type_can_fail(ZigType *type_entry);
 bool fn_eval_cacheable(Scope *scope, ZigType *return_type);
 AstNode *type_decl_node(ZigType *type_entry);
 
-ZigType *get_primitive_type(CodeGen *g, Buf *name);
+Error get_primitive_type(CodeGen *g, Buf *name, ZigType **result);
 
 bool calling_convention_allows_zig_types(CallingConvention cc);
 const char *calling_convention_name(CallingConvention cc);
src/codegen.cpp
@@ -7326,7 +7326,7 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {
     import->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
 
     ZigList<ErrorMsg *> errors = {0};
-    int err = parse_h_file(import, &errors, buf_ptr(full_path), g, nullptr);
+    Error err = parse_h_file(import, &errors, buf_ptr(full_path), g, nullptr);
 
     if (err == ErrorCCompileErrors && errors.length > 0) {
         for (size_t i = 0; i < errors.length; i += 1) {
@@ -7446,7 +7446,7 @@ static void gen_root_source(CodeGen *g) {
         return;
 
     Buf *source_code = buf_alloc();
-    int err;
+    Error err;
     // No need for using the caching system for this file fetch because it is handled
     // separately.
     if ((err = os_fetch_file_path(resolved_path, source_code, true))) {
@@ -7514,7 +7514,7 @@ void codegen_add_assembly(CodeGen *g, Buf *path) {
 
 static void gen_global_asm(CodeGen *g) {
     Buf contents = BUF_INIT;
-    int err;
+    Error err;
     for (size_t i = 0; i < g->assembly_files.length; i += 1) {
         Buf *asm_file = g->assembly_files.at(i);
         // No need to use the caching system for these fetches because they
src/error.cpp
@@ -7,8 +7,8 @@
 
 #include "error.hpp"
 
-const char *err_str(int err) {
-    switch ((enum Error)err) {
+const char *err_str(Error err) {
+    switch (err) {
         case ErrorNone: return "(no error)";
         case ErrorNoMem: return "out of memory";
         case ErrorInvalidFormat: return "invalid format";
@@ -32,6 +32,7 @@ const char *err_str(int err) {
         case ErrorUnsupportedOperatingSystem: return "unsupported operating system";
         case ErrorSharingViolation: return "sharing violation";
         case ErrorPipeBusy: return "pipe busy";
+        case ErrorPrimitiveTypeNotFound: return "primitive type not found";
     }
     return "(invalid error)";
 }
src/error.hpp
@@ -8,6 +8,8 @@
 #ifndef ERROR_HPP
 #define ERROR_HPP
 
+#include <assert.h>
+
 enum Error {
     ErrorNone,
     ErrorNoMem,
@@ -32,8 +34,13 @@ enum Error {
     ErrorUnsupportedOperatingSystem,
     ErrorSharingViolation,
     ErrorPipeBusy,
+    ErrorPrimitiveTypeNotFound,
 };
 
-const char *err_str(int err);
+const char *err_str(Error err);
+
+static inline void assertNoError(Error err) {
+    assert(err == ErrorNone);
+}
 
 #endif
src/ir.cpp
@@ -3055,10 +3055,10 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
                 add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
                 variable_entry->value->type = codegen->builtin_types.entry_invalid;
             } else {
-                ZigType *type = get_primitive_type(codegen, name);
-                if (type != nullptr) {
+                ZigType *type;
+                if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) {
                     add_node_error(codegen, node,
-                            buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));
+                            buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
                     variable_entry->value->type = codegen->builtin_types.entry_invalid;
                 } else {
                     Tld *tld = find_decl(codegen, parent_scope, name);
@@ -3488,6 +3488,7 @@ static IrInstruction *ir_gen_null_literal(IrBuilder *irb, Scope *scope, AstNode
 }
 
 static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
+    Error err;
     assert(node->type == NodeTypeSymbol);
 
     Buf *variable_name = node->data.symbol_expr.symbol;
@@ -3501,8 +3502,15 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
         return &const_instruction->base;
     }
 
-    ZigType *primitive_type = get_primitive_type(irb->codegen, variable_name);
-    if (primitive_type != nullptr) {
+    ZigType *primitive_type;
+    if ((err = get_primitive_type(irb->codegen, variable_name, &primitive_type))) {
+        if (err == ErrorOverflow) {
+            add_node_error(irb->codegen, node,
+                buf_sprintf("primitive integer type '%s' exceeds maximum bit width of 65535",
+                    buf_ptr(variable_name)));
+            return irb->codegen->invalid_instruction;
+        }
+    } else {
         IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type);
         if (lval == LValPtr) {
             return ir_build_ref(irb, scope, node, value, false, false);
@@ -6302,7 +6310,6 @@ static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigTyp
         }
     }
 
-    err_set_type->is_copyable = true;
     err_set_type->type_ref = g->builtin_types.entry_global_error_set->type_ref;
     err_set_type->di_type = g->builtin_types.entry_global_error_set->di_type;
     err_set_type->data.error_set.err_count = count;
@@ -6341,7 +6348,6 @@ static ZigType *make_err_set_with_one_item(CodeGen *g, Scope *parent_scope, AstN
     ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
     buf_resize(&err_set_type->name, 0);
     buf_appendf(&err_set_type->name, "error.{%s}", buf_ptr(&err_entry->name));
-    err_set_type->is_copyable = true;
     err_set_type->type_ref = g->builtin_types.entry_global_error_set->type_ref;
     err_set_type->di_type = g->builtin_types.entry_global_error_set->di_type;
     err_set_type->data.error_set.err_count = 1;
@@ -6362,7 +6368,6 @@ static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, A
     Buf *type_name = get_anon_type_name(irb->codegen, irb->exec, "error set", node);
     ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
     buf_init_from_buf(&err_set_type->name, type_name);
-    err_set_type->is_copyable = true;
     err_set_type->data.error_set.err_count = err_count;
     err_set_type->type_ref = irb->codegen->builtin_types.entry_global_error_set->type_ref;
     err_set_type->di_type = irb->codegen->builtin_types.entry_global_error_set->di_type;
@@ -8208,7 +8213,6 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp
     }
     free(errors);
 
-    err_set_type->is_copyable = true;
     err_set_type->type_ref = ira->codegen->builtin_types.entry_global_error_set->type_ref;
     err_set_type->di_type = ira->codegen->builtin_types.entry_global_error_set->di_type;
     err_set_type->data.error_set.err_count = intersection_list.length;
@@ -17650,7 +17654,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
 
     ZigList<ErrorMsg *> errors = {0};
 
-    int err;
+    Error err;
     if ((err = parse_h_buf(child_import, &errors, &cimport_scope->buf, ira->codegen, node))) {
         if (err != ErrorCCompileErrors) {
             ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));
@@ -17766,7 +17770,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru
 
     // load from file system into const expr
     Buf *file_contents = buf_alloc();
-    int err;
+    Error err;
     if ((err = file_fetch(ira->codegen, file_path, file_contents))) {
         if (err == ErrorFileNotFound) {
             ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(file_path)));
@@ -18252,7 +18256,7 @@ static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstruct
 
     IrInstruction *bit_count_value = instruction->bit_count->child;
     uint64_t bit_count;
-    if (!ir_resolve_unsigned(ira, bit_count_value, ira->codegen->builtin_types.entry_u32, &bit_count))
+    if (!ir_resolve_unsigned(ira, bit_count_value, ira->codegen->builtin_types.entry_u16, &bit_count))
         return ira->codegen->invalid_instruction;
 
     return ir_const_type(ira, &instruction->base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count));
src/os.cpp
@@ -793,7 +793,7 @@ Error os_file_exists(Buf *full_path, bool *result) {
 }
 
 #if defined(ZIG_OS_POSIX)
-static int os_exec_process_posix(const char *exe, ZigList<const char *> &args,
+static Error os_exec_process_posix(const char *exe, ZigList<const char *> &args,
         Termination *term, Buf *out_stderr, Buf *out_stdout)
 {
     int stdin_pipe[2];
@@ -872,7 +872,7 @@ static int os_exec_process_posix(const char *exe, ZigList<const char *> &args,
 //    LocalFree(messageBuffer);
 //}
 
-static int os_exec_process_windows(const char *exe, ZigList<const char *> &args,
+static Error os_exec_process_windows(const char *exe, ZigList<const char *> &args,
         Termination *term, Buf *out_stderr, Buf *out_stdout)
 {
     Buf command_line = BUF_INIT;
@@ -983,7 +983,7 @@ static int os_exec_process_windows(const char *exe, ZigList<const char *> &args,
     CloseHandle(piProcInfo.hProcess);
     CloseHandle(piProcInfo.hThread);
 
-    return 0;
+    return ErrorNone;
 }
 #endif
 
@@ -1003,7 +1003,7 @@ Error os_execv(const char *exe, const char **argv) {
 #endif
 }
 
-int os_exec_process(const char *exe, ZigList<const char *> &args,
+Error os_exec_process(const char *exe, ZigList<const char *> &args,
         Termination *term, Buf *out_stderr, Buf *out_stdout)
 {
 #if defined(ZIG_OS_WINDOWS)
@@ -1027,7 +1027,7 @@ void os_write_file(Buf *full_path, Buf *contents) {
         zig_panic("close failed");
 }
 
-int os_copy_file(Buf *src_path, Buf *dest_path) {
+Error os_copy_file(Buf *src_path, Buf *dest_path) {
     FILE *src_f = fopen(buf_ptr(src_path), "rb");
     if (!src_f) {
         int err = errno;
@@ -1074,7 +1074,7 @@ int os_copy_file(Buf *src_path, Buf *dest_path) {
         if (feof(src_f)) {
             fclose(src_f);
             fclose(dest_f);
-            return 0;
+            return ErrorNone;
         }
     }
 }
@@ -1197,7 +1197,7 @@ bool os_stderr_tty(void) {
 }
 
 #if defined(ZIG_OS_POSIX)
-static int os_buf_to_tmp_file_posix(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
+static Error os_buf_to_tmp_file_posix(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
     const char *tmp_dir = getenv("TMPDIR");
     if (!tmp_dir) {
         tmp_dir = P_tmpdir;
@@ -1221,12 +1221,12 @@ static int os_buf_to_tmp_file_posix(Buf *contents, Buf *suffix, Buf *out_tmp_pat
     if (fclose(f))
         zig_panic("close failed");
 
-    return 0;
+    return ErrorNone;
 }
 #endif
 
 #if defined(ZIG_OS_WINDOWS)
-static int os_buf_to_tmp_file_windows(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
+static Error os_buf_to_tmp_file_windows(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
     char tmp_dir[MAX_PATH + 1];
     if (GetTempPath(MAX_PATH, tmp_dir) == 0) {
         zig_panic("GetTempPath failed");
@@ -1255,11 +1255,11 @@ static int os_buf_to_tmp_file_windows(Buf *contents, Buf *suffix, Buf *out_tmp_p
     if (fclose(f)) {
         zig_panic("fclose failed");
     }
-    return 0;
+    return ErrorNone;
 }
 #endif
 
-int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
+Error os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
 #if defined(ZIG_OS_WINDOWS)
     return os_buf_to_tmp_file_windows(contents, suffix, out_tmp_path);
 #elif defined(ZIG_OS_POSIX)
@@ -1269,17 +1269,17 @@ int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
 #endif
 }
 
-int os_delete_file(Buf *path) {
+Error os_delete_file(Buf *path) {
     if (remove(buf_ptr(path))) {
         return ErrorFileSystem;
     } else {
-        return 0;
+        return ErrorNone;
     }
 }
 
-int os_rename(Buf *src_path, Buf *dest_path) {
+Error os_rename(Buf *src_path, Buf *dest_path) {
     if (buf_eql_buf(src_path, dest_path)) {
-        return 0;
+        return ErrorNone;
     }
 #if defined(ZIG_OS_WINDOWS)
     if (!MoveFileExA(buf_ptr(src_path), buf_ptr(dest_path), MOVEFILE_REPLACE_EXISTING)) {
@@ -1290,7 +1290,7 @@ int os_rename(Buf *src_path, Buf *dest_path) {
         return ErrorFileSystem;
     }
 #endif
-    return 0;
+    return ErrorNone;
 }
 
 double os_get_time(void) {
src/os.hpp
@@ -13,7 +13,6 @@
 #include "error.hpp"
 #include "zig_llvm.h"
 #include "windows_sdk.h"
-#include "result.hpp"
 
 #include <stdio.h>
 #include <inttypes.h>
@@ -85,7 +84,7 @@ struct OsTimeStamp {
 int os_init(void);
 
 void os_spawn_process(const char *exe, ZigList<const char *> &args, Termination *term);
-int os_exec_process(const char *exe, ZigList<const char *> &args,
+Error os_exec_process(const char *exe, ZigList<const char *> &args,
         Termination *term, Buf *out_stderr, Buf *out_stdout);
 Error os_execv(const char *exe, const char **argv);
 
@@ -109,7 +108,7 @@ Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);
 void os_file_close(OsFile file);
 
 void os_write_file(Buf *full_path, Buf *contents);
-int os_copy_file(Buf *src_path, Buf *dest_path);
+Error os_copy_file(Buf *src_path, Buf *dest_path);
 
 Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang);
 Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang);
@@ -119,12 +118,12 @@ Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);
 bool os_stderr_tty(void);
 void os_stderr_set_color(TermColor color);
 
-int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path);
-int os_delete_file(Buf *path);
+Error os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path);
+Error os_delete_file(Buf *path);
 
 Error ATTRIBUTE_MUST_USE os_file_exists(Buf *full_path, bool *result);
 
-int os_rename(Buf *src_path, Buf *dest_path);
+Error os_rename(Buf *src_path, Buf *dest_path);
 double os_get_time(void);
 
 bool os_is_sep(uint8_t c);
src/result.hpp
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2018 Andrew Kelley
- *
- * This file is part of zig, which is MIT licensed.
- * See http://opensource.org/licenses/MIT
- */
-
-#ifndef ZIG_RESULT_HPP
-#define ZIG_RESULT_HPP
-
-#include "error.hpp"
-
-#include <assert.h>
-
-static inline void assertNoError(Error err) {
-    assert(err == ErrorNone);
-}
-
-template<typename T>
-struct Result {
-    T data;
-    Error err;
-
-    Result(T x) : data(x), err(ErrorNone) {}
-
-    Result(Error err) : err(err) {
-        assert(err != ErrorNone);
-    }
-
-    T unwrap() {
-        assert(err == ErrorNone);
-        return data;
-    }
-};
-
-#endif
src/translate_c.cpp
@@ -436,7 +436,8 @@ static AstNode *get_global(Context *c, Buf *name) {
         if (entry)
             return entry->value;
     }
-    if (get_primitive_type(c->codegen, name) != nullptr) {
+    ZigType *type;
+    if (get_primitive_type(c->codegen, name, &type) != ErrorPrimitiveTypeNotFound) {
         return trans_create_node_symbol(c, name);
     }
     return nullptr;
@@ -4682,10 +4683,10 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
     }
 }
 
-int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source,
+Error parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source,
         CodeGen *codegen, AstNode *source_node)
 {
-    int err;
+    Error err;
     Buf tmp_file_path = BUF_INIT;
     if ((err = os_buf_to_tmp_file(source, buf_create_from_str(".h"), &tmp_file_path))) {
         return err;
@@ -4698,7 +4699,7 @@ int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *sour
     return err;
 }
 
-int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file,
+Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file,
         CodeGen *codegen, AstNode *source_node)
 {
     Context context = {0};
@@ -4865,5 +4866,5 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
 
     import->root = c->root;
 
-    return 0;
+    return ErrorNone;
 }
src/translate_c.hpp
@@ -11,10 +11,10 @@
 
 #include "all_types.hpp"
 
-int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file,
+Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file,
         CodeGen *codegen, AstNode *source_node);
 
-int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source,
+Error parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source,
         CodeGen *codegen, AstNode *source_node);
 
 #endif
test/compile_errors.zig
@@ -1,6 +1,19 @@
 const tests = @import("tests.zig");
 
 pub fn addCases(cases: *tests.CompileErrorContext) void {
+    cases.add(
+        "exceeded maximum bit width of integer",
+        \\export fn entry1() void {
+        \\    const T = @IntType(false, 65536);
+        \\}
+        \\export fn entry2() void {
+        \\    var x: i65536 = 1;
+        \\}
+    ,
+        ".tmp_source.zig:2:31: error: integer value 65536 cannot be implicitly casted to type 'u16'",
+        ".tmp_source.zig:5:12: error: primitive integer type 'i65536' exceeds maximum bit width of 65535",
+    );
+
     cases.add(
         "Panic declared with wrong type signature in tests",
         \\test "" {}
@@ -534,15 +547,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
         ".tmp_source.zig:1:9: error: parameter of type 'fn(var)var' must be declared comptime",
     );
 
-    cases.add(
-        "bit count of @IntType too large",
-        \\comptime {
-        \\    _ = @IntType(false, @import("std").math.maxInt(u32) + 1);
-        \\}
-    ,
-        ".tmp_source.zig:2:57: error: integer value 4294967296 cannot be implicitly casted to type 'u32'",
-    );
-
     cases.add(
         "optional pointer to void in extern struct",
         \\const Foo = extern struct.{
@@ -4278,7 +4282,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
         \\    const a: u16 = 300;
         \\}
     ,
-        ".tmp_source.zig:1:1: error: declaration shadows type 'u16'",
+        ".tmp_source.zig:1:1: error: declaration shadows primitive type 'u16'",
     );
 
     cases.add(