diff --git a/lib/std/io.zig b/lib/std/io.zig index 25106e24be..09844bf055 100644 --- a/lib/std/io.zig +++ b/lib/std/io.zig @@ -17,9 +17,15 @@ const File = std.fs.File; const testing = std.testing; pub const Mode = enum { + /// I/O operates normally, waiting for the operating system syscalls to complete. blocking, + + /// I/O functions are generated async and rely on a global event loop. Event-based I/O. evented, }; + +/// The application's chosen I/O mode. This defaults to `Mode.blocking` but can be overridden +/// by `root.event_loop`. pub const mode: Mode = if (@hasDecl(root, "io_mode")) root.io_mode else if (@hasDecl(root, "event_loop")) diff --git a/lib/std/special/docs/main.js b/lib/std/special/docs/main.js index 879b75872c..7e5a9c4c0e 100644 --- a/lib/std/special/docs/main.js +++ b/lib/std/special/docs/main.js @@ -43,6 +43,7 @@ var typeKinds = indexTypeKinds(); var typeTypeId = findTypeTypeId(); + var pointerSizeEnum = { One: 0, Many: 1, Slice: 2, C: 3 }; // for each package, is an array with packages to get to this one var canonPkgPaths = computeCanonicalPackagePaths(); @@ -376,24 +377,41 @@ } } - function typeIndexName(typeIndex, wantHtml, wantLink, fnDecl, skipFnName) { + function typeIndexName(typeIndex, wantHtml, wantLink, fnDecl, linkFnNameDecl) { var typeObj = zigAnalysis.types[typeIndex]; + var declNameOk = declCanRepresentTypeKind(typeObj.kind); if (wantLink) { var declIndex = getCanonTypeDecl(typeIndex); var declPath = getCanonDeclPath(declIndex); - var haveLink = declPath != null; - var typeNameHtml = typeName(typeObj, true, !haveLink, fnDecl, skipFnName); - if (haveLink) { - return '' + typeNameHtml + ''; + if (declPath == null) { + return typeName(typeObj, wantHtml, wantLink, fnDecl, linkFnNameDecl); + } + var name = (wantLink && declCanRepresentTypeKind(typeObj.kind)) ? + declPath.declNames[declPath.declNames.length - 1] : + typeName(typeObj, wantHtml, false, fnDecl, linkFnNameDecl); + if (wantLink && wantHtml) { + return '' + name + ''; } else { - return typeNameHtml; + return name; } } else { - return typeName(typeObj, wantHtml, false, fnDecl, skipFnName); + return typeName(typeObj, wantHtml, false, fnDecl, linkFnNameDecl); } } - function typeName(typeObj, wantHtml, wantSubLink, fnDecl, skipFnName) { + function shouldSkipParamName(typeIndex, paramName) { + var typeObj = zigAnalysis.types[typeIndex]; + if (typeObj.kind === typeKinds.Pointer && getPtrSize(typeObj) === pointerSizeEnum.One) { + typeIndex = typeObj.elem; + } + return typeIndexName(typeIndex, false, true).toLowerCase() === paramName; + } + + function getPtrSize(typeObj) { + return (typeObj.len == null) ? pointerSizeEnum.One : typeObj.len; + } + + function typeName(typeObj, wantHtml, wantSubLink, fnDecl, linkFnNameDecl) { switch (typeObj.kind) { case typeKinds.Array: var name = "["; @@ -408,17 +426,17 @@ case typeKinds.Pointer: var name = ""; switch (typeObj.len) { - case 0: + case pointerSizeEnum.One: default: name += "*"; break; - case 1: + case pointerSizeEnum.Many: name += "[*]"; break; - case 2: + case pointerSizeEnum.Slice: name += "[]"; break; - case 3: + case pointerSizeEnum.C: name += "[*c]"; break; } @@ -542,8 +560,15 @@ var payloadHtml = ""; if (wantHtml) { payloadHtml += 'fn'; - if (fnDecl != null && !skipFnName) { - payloadHtml += ' ' + escapeHtml(fnDecl.name) + ''; + if (fnDecl != null) { + payloadHtml += ' '; + if (linkFnNameDecl != null) { + payloadHtml += '' + + escapeHtml(fnDecl.name) + ''; + } else { + payloadHtml += escapeHtml(fnDecl.name); + } + payloadHtml += ''; } } else { payloadHtml += 'fn' @@ -554,7 +579,21 @@ if (i != 0) { payloadHtml += ', '; } + var argTypeIndex = typeObj.args[i]; + + if (fnDecl != null && zigAnalysis.astNodes[fnDecl.src].fields != null) { + var paramDeclIndex = zigAnalysis.astNodes[fnDecl.src].fields[i]; + var paramName = zigAnalysis.astNodes[paramDeclIndex].name; + + if (paramName != null) { + // skip if it matches the type name + if (argTypeIndex == null || !shouldSkipParamName(argTypeIndex, paramName)) { + payloadHtml += paramName + ': '; + } + } + } + if (argTypeIndex != null) { payloadHtml += typeIndexName(argTypeIndex, wantHtml, wantSubLink); } else if (wantHtml) { @@ -645,7 +684,7 @@ } function renderValue(decl) { - domFnProtoCode.innerHTML = 'pub const ' + + domFnProtoCode.innerHTML = 'const ' + escapeHtml(decl.name) + ': ' + typeIndexName(decl.type, true, true); var docs = zigAnalysis.astNodes[decl.src].docs; @@ -658,7 +697,7 @@ } function renderVar(decl) { - domFnProtoCode.innerHTML = 'pub var ' + + domFnProtoCode.innerHTML = 'var ' + escapeHtml(decl.name) + ': ' + typeIndexName(decl.type, true, true); var docs = zigAnalysis.astNodes[decl.src].docs; @@ -748,21 +787,15 @@ } if (fnsList.length !== 0) { - resizeDomList(domListFns, fnsList.length, - ''); + resizeDomList(domListFns, fnsList.length, ''); for (var i = 0; i < fnsList.length; i += 1) { var decl = fnsList[i]; var trDom = domListFns.children[i]; - var tdName = trDom.children[0]; - var tdNameA = tdName.children[0]; - var tdType = trDom.children[1]; - var tdDesc = trDom.children[2]; + var tdFnCode = trDom.children[0]; + var tdDesc = trDom.children[1]; - tdNameA.setAttribute('href', navLinkDecl(decl.name)); - tdNameA.textContent = decl.name; - - tdType.innerHTML = typeIndexName(decl.type, true, true, decl, true); + tdFnCode.innerHTML = typeIndexName(decl.type, true, true, decl, navLinkDecl(decl.name)); var docs = zigAnalysis.astNodes[decl.src].docs; if (docs != null) { @@ -776,14 +809,24 @@ if (container.fields != null && container.fields.length !== 0) { resizeDomList(domListFields, container.fields.length, '
'); + + var containerNode = zigAnalysis.astNodes[container.src]; for (var i = 0; i < container.fields.length; i += 1) { var field = container.fields[i]; + var fieldNode = zigAnalysis.astNodes[containerNode.fields[i]]; var divDom = domListFields.children[i]; - var html = '
' + escapeHtml(field.name) + ": " +
-                    typeIndexName(field.type, true, true) + ',
'; + var html = '
' + escapeHtml(fieldNode.name);
 
-                var docs = zigAnalysis.astNodes[field.src].docs;
+                if (container.kind === typeKinds.Enum) {
+                    html += ' = ' + field + '';
+                } else {
+                    html += ": " + typeIndexName(field, true, true);
+                }
+
+                html += ',
'; + + var docs = fieldNode.docs; if (docs != null) { html += markdown(docs); } diff --git a/src/dump_analysis.cpp b/src/dump_analysis.cpp index 35a249c92a..6a3593ed58 100644 --- a/src/dump_analysis.cpp +++ b/src/dump_analysis.cpp @@ -216,6 +216,21 @@ static void jw_int(JsonWriter *jw, int64_t x) { jw_pop_state(jw); } +static void jw_bigint(JsonWriter *jw, const BigInt *x) { + assert(jw->state[jw->state_index] == JsonWriterStateValue); + Buf *str = buf_alloc(); + bigint_append_buf(str, x, 10); + + if (bigint_fits_in_bits(x, 52, true)) { + fprintf(jw->f, "%s", buf_ptr(str)); + } else { + fprintf(jw->f, "\"%s\"", buf_ptr(str)); + } + jw_pop_state(jw); + + buf_destroy(str); +} + static void jw_string(JsonWriter *jw, const char *s) { assert(jw->state[jw->state_index] == JsonWriterStateValue); jw_write_escaped_string(jw, s); @@ -732,23 +747,6 @@ static void anal_dump_pointer_attrs(AnalDumpCtx *ctx, ZigType *ty) { anal_dump_type_ref(ctx, ty->data.pointer.child_type); } -static void anal_dump_struct_field(AnalDumpCtx *ctx, const TypeStructField *struct_field) { - JsonWriter *jw = &ctx->jw; - - jw_begin_object(jw); - - jw_object_field(jw, "name"); - jw_string(jw, buf_ptr(struct_field->name)); - - jw_object_field(jw, "type"); - anal_dump_type_ref(ctx, struct_field->type_entry); - - jw_object_field(jw, "src"); - anal_dump_node_ref(ctx, struct_field->decl_node); - - jw_end_object(jw); -} - static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { JsonWriter *jw = &ctx->jw; jw_array_elem(jw); @@ -771,6 +769,10 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { jw_object_field(jw, "name"); jw_string(jw, buf_ptr(&ty->name)); + + jw_object_field(jw, "src"); + anal_dump_node_ref(ctx, ty->data.structure.decl_node); + { jw_object_field(jw, "pubDecls"); jw_begin_array(jw); @@ -817,7 +819,7 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { for(size_t i = 0; i < ty->data.structure.src_field_count; i += 1) { jw_array_elem(jw); - anal_dump_struct_field(ctx, &ty->data.structure.fields[i]); + anal_dump_type_ref(ctx, ty->data.structure.fields[i].type_entry); } jw_end_array(jw); } @@ -827,7 +829,124 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { jw_object_field(jw, "file"); anal_dump_file_ref(ctx, path_buf); + } + break; + } + case ZigTypeIdUnion: { + jw_object_field(jw, "name"); + jw_string(jw, buf_ptr(&ty->name)); + jw_object_field(jw, "src"); + anal_dump_node_ref(ctx, ty->data.unionation.decl_node); + + { + jw_object_field(jw, "pubDecls"); + jw_begin_array(jw); + + ScopeDecls *decls_scope = ty->data.unionation.decls_scope; + auto it = decls_scope->decl_table.entry_iterator(); + for (;;) { + auto *entry = it.next(); + if (!entry) + break; + + Tld *tld = entry->value; + if (tld->visib_mod == VisibModPub) { + jw_array_elem(jw); + anal_dump_decl_ref(ctx, tld); + } + } + jw_end_array(jw); + } + + { + jw_object_field(jw, "privDecls"); + jw_begin_array(jw); + + ScopeDecls *decls_scope = ty->data.unionation.decls_scope; + auto it = decls_scope->decl_table.entry_iterator(); + for (;;) { + auto *entry = it.next(); + if (!entry) + break; + + Tld *tld = entry->value; + if (tld->visib_mod == VisibModPrivate) { + jw_array_elem(jw); + anal_dump_decl_ref(ctx, tld); + } + } + jw_end_array(jw); + } + + if (ty->data.unionation.src_field_count != 0) { + jw_object_field(jw, "fields"); + jw_begin_array(jw); + + for(size_t i = 0; i < ty->data.unionation.src_field_count; i += 1) { + jw_array_elem(jw); + anal_dump_type_ref(ctx, ty->data.unionation.fields[i].type_entry); + } + jw_end_array(jw); + } + break; + } + case ZigTypeIdEnum: { + jw_object_field(jw, "name"); + jw_string(jw, buf_ptr(&ty->name)); + + jw_object_field(jw, "src"); + anal_dump_node_ref(ctx, ty->data.enumeration.decl_node); + + { + jw_object_field(jw, "pubDecls"); + jw_begin_array(jw); + + ScopeDecls *decls_scope = ty->data.enumeration.decls_scope; + auto it = decls_scope->decl_table.entry_iterator(); + for (;;) { + auto *entry = it.next(); + if (!entry) + break; + + Tld *tld = entry->value; + if (tld->visib_mod == VisibModPub) { + jw_array_elem(jw); + anal_dump_decl_ref(ctx, tld); + } + } + jw_end_array(jw); + } + + { + jw_object_field(jw, "privDecls"); + jw_begin_array(jw); + + ScopeDecls *decls_scope = ty->data.enumeration.decls_scope; + auto it = decls_scope->decl_table.entry_iterator(); + for (;;) { + auto *entry = it.next(); + if (!entry) + break; + + Tld *tld = entry->value; + if (tld->visib_mod == VisibModPrivate) { + jw_array_elem(jw); + anal_dump_decl_ref(ctx, tld); + } + } + jw_end_array(jw); + } + + if (ty->data.enumeration.src_field_count != 0) { + jw_object_field(jw, "fields"); + jw_begin_array(jw); + + for(size_t i = 0; i < ty->data.enumeration.src_field_count; i += 1) { + jw_array_elem(jw); + jw_bigint(jw, &ty->data.enumeration.fields[i].value); + } + jw_end_array(jw); } break; } @@ -974,6 +1093,45 @@ static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) { jw_string(jw, buf_ptr(doc_comments_buf)); } + const Buf *name_buf; + switch (node->type) { + case NodeTypeStructField: + name_buf = node->data.struct_field.name; + break; + case NodeTypeParamDecl: + name_buf = node->data.param_decl.name; + break; + default: + name_buf = nullptr; + break; + } + if (name_buf != nullptr) { + jw_object_field(jw, "name"); + jw_string(jw, buf_ptr(name_buf)); + } + + const ZigList *fieldNodes; + switch (node->type) { + case NodeTypeContainerDecl: + fieldNodes = &node->data.container_decl.fields; + break; + case NodeTypeFnProto: + fieldNodes = &node->data.fn_proto.params; + break; + default: + fieldNodes = nullptr; + break; + } + if (fieldNodes != nullptr) { + jw_object_field(jw, "fields"); + jw_begin_array(jw); + for (size_t i = 0; i < fieldNodes->length; i += 1) { + jw_array_elem(jw); + anal_dump_node_ref(ctx, fieldNodes->at(i)); + } + jw_end_array(jw); + } + jw_end_object(jw); } diff --git a/src/ir.cpp b/src/ir.cpp index 0e6153ebcd..7dd141423c 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -13122,7 +13122,6 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod return true; } - static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { if (type_is_invalid(value->value.type)) return nullptr; @@ -13143,11 +13142,11 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray); ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val; - if (array_val->data.x_array.special == ConstArraySpecialBuf) { - return array_val->data.x_array.data.s_buf; - } expand_undef_array(ira->codegen, array_val); size_t len = bigint_as_usize(&len_field->data.x_bigint); + if (array_val->data.x_array.special == ConstArraySpecialBuf && len == buf_len(array_val->data.x_array.data.s_buf)) { + return array_val->data.x_array.data.s_buf; + } Buf *result = buf_alloc(); buf_resize(result, len); for (size_t i = 0; i < len; i += 1) { @@ -17952,7 +17951,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ union_val->special = ConstValSpecialStatic; bigint_init_bigint(&union_val->data.x_union.tag, &field->enum_field->value); union_val->data.x_union.payload = payload_val; - } else { + } else if (bare_type->data.unionation.layout != ContainerLayoutExtern) { TypeUnionField *actual_field = find_union_field_by_tag(bare_type, &union_val->data.x_union.tag); if (actual_field == nullptr) zig_unreachable(); diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index 95cb98f8eb..95d2dbac93 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -35,6 +35,7 @@ comptime { _ = @import("behavior/bugs/3046.zig"); _ = @import("behavior/bugs/3112.zig"); _ = @import("behavior/bugs/3367.zig"); + _ = @import("behavior/bugs/3384.zig"); _ = @import("behavior/bugs/394.zig"); _ = @import("behavior/bugs/421.zig"); _ = @import("behavior/bugs/529.zig"); diff --git a/test/stage1/behavior/bugs/3367.zig b/test/stage1/behavior/bugs/3367.zig index 06b633df67..3df3adbff7 100644 --- a/test/stage1/behavior/bugs/3367.zig +++ b/test/stage1/behavior/bugs/3367.zig @@ -1,6 +1,3 @@ -const std = @import("std"); -const expect = std.testing.expect; - const Foo = struct { usingnamespace Mixin; }; diff --git a/test/stage1/behavior/bugs/3384.zig b/test/stage1/behavior/bugs/3384.zig new file mode 100644 index 0000000000..789b0be516 --- /dev/null +++ b/test/stage1/behavior/bugs/3384.zig @@ -0,0 +1,11 @@ +const std = @import("std"); +const expect = std.testing.expect; + +test "resolve array slice using builtin" { + expect(@hasDecl(@This(), "std") == true); + expect(@hasDecl(@This(), "std"[0..0]) == false); + expect(@hasDecl(@This(), "std"[0..1]) == false); + expect(@hasDecl(@This(), "std"[0..2]) == false); + expect(@hasDecl(@This(), "std"[0..3]) == true); + expect(@hasDecl(@This(), "std"[0..]) == true); +} diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig index d340a52d1e..f5e9ec09a8 100644 --- a/test/stage1/behavior/union.zig +++ b/test/stage1/behavior/union.zig @@ -511,3 +511,13 @@ test "union with comptime_int tag" { }; comptime expect(@TagType(@TagType(Union)) == comptime_int); } + +test "extern union doesn't trigger field check at comptime" { + const U = extern union { + x: u32, + y: u8, + }; + + const x = U{ .x = 0x55AAAA55 }; + comptime expect(x.y == 0x55); +}