From f67ca206557de58df91011744f656ed049d36372 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 21 May 2019 17:07:40 +0200 Subject: [PATCH 1/3] Make use work with arbitrary structs --- src/analyze.cpp | 46 ++++++++++++++++++++------------- test/stage1/behavior/struct.zig | 11 ++++++++ 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index d6396832c4..58b91b343d 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3754,49 +3754,59 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { analyze_fn_ir(g, fn_table_entry, return_type_node); } -static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node, ScopeDecls* decls_scope) { +static void add_symbols_from_struct(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node, ScopeDecls* decls_scope) { if (src_use_node->data.use.resolution == TldResolutionUnresolved) { preview_use_decl(g, src_use_node, decls_scope); } - ConstExprValue *use_target_value = src_use_node->data.use.using_namespace_value; - if (type_is_invalid(use_target_value->type)) { + ConstExprValue *use_expr = src_use_node->data.use.using_namespace_value; + if (type_is_invalid(use_expr->type)) { decls_scope->any_imports_failed = true; return; } dst_use_node->data.use.resolution = TldResolutionOk; - assert(use_target_value->special != ConstValSpecialRuntime); + assert(use_expr->special != ConstValSpecialRuntime); - ZigType *target_import = use_target_value->data.x_type; - assert(target_import); + // The source struct for the imported symbols + ZigType *src_ty = use_expr->data.x_type; + assert(src_ty); - if (target_import->id != ZigTypeIdStruct) { + if (src_ty->id != ZigTypeIdStruct) { add_node_error(g, dst_use_node, - buf_sprintf("expected struct, found '%s'", buf_ptr(&target_import->name))); + buf_sprintf("expected struct, found '%s'", buf_ptr(&src_ty->name))); decls_scope->any_imports_failed = true; return; } - if (get_container_scope(target_import)->any_imports_failed) { + // The source scope for the imported symbols + ScopeDecls *src_scope = get_container_scope(src_ty); + // The top-level container where the symbols are defined, it's used in the + // loop below in order to exclude the ones coming from an import statement + ZigType *src_import = get_scope_import(reinterpret_cast(src_scope)); + assert(src_import && src_import->id == ZigTypeIdStruct); + + if (src_scope->any_imports_failed) { decls_scope->any_imports_failed = true; } - auto it = get_container_scope(target_import)->decl_table.entry_iterator(); + auto it = src_scope->decl_table.entry_iterator(); for (;;) { auto *entry = it.next(); if (!entry) break; + Buf *target_tld_name = entry->key; Tld *target_tld = entry->value; - if (target_tld->import != target_import || - target_tld->visib_mod == VisibModPrivate) - { + + if (target_tld->visib_mod == VisibModPrivate) { continue; } - Buf *target_tld_name = entry->key; + if (target_tld->import != src_import) { + continue; + } auto existing_entry = decls_scope->decl_table.put_unique(target_tld_name, target_tld); if (existing_entry) { @@ -3811,10 +3821,10 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode * } } - for (size_t i = 0; i < get_container_scope(target_import)->use_decls.length; i += 1) { - AstNode *use_decl_node = get_container_scope(target_import)->use_decls.at(i); + for (size_t i = 0; i < src_scope->use_decls.length; i += 1) { + AstNode *use_decl_node = src_scope->use_decls.at(i); if (use_decl_node->data.use.visib_mod != VisibModPrivate) - add_symbols_from_import(g, use_decl_node, dst_use_node, decls_scope); + add_symbols_from_struct(g, use_decl_node, dst_use_node, decls_scope); } } @@ -3826,7 +3836,7 @@ void resolve_use_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) { { return; } - add_symbols_from_import(g, node, node, decls_scope); + add_symbols_from_struct(g, node, node, decls_scope); } void preview_use_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) { diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig index c38359be24..d7bbee5d15 100644 --- a/test/stage1/behavior/struct.zig +++ b/test/stage1/behavior/struct.zig @@ -549,3 +549,14 @@ test "packed struct with fp fields" { expectEqual(f32(11.0), s.data[1]); expectEqual(f32(20.0), s.data[2]); } + +test "use within struct scope" { + const S = struct { + use struct { + pub fn inner() i32 { + return 42; + } + }; + }; + expectEqual(i32(42), S.inner()); +} From 86b3007b945d2145bc7467625c658fd5480b5135 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 24 May 2019 13:20:44 +0200 Subject: [PATCH 2/3] Reject slices in use expressions Co-Authored-By: emekoi --- src/analyze.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 58b91b343d..a1f0571c5b 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3773,7 +3773,7 @@ static void add_symbols_from_struct(CodeGen *g, AstNode *src_use_node, AstNode * ZigType *src_ty = use_expr->data.x_type; assert(src_ty); - if (src_ty->id != ZigTypeIdStruct) { + if (src_ty->id != ZigTypeIdStruct || is_slice(src_ty)) { add_node_error(g, dst_use_node, buf_sprintf("expected struct, found '%s'", buf_ptr(&src_ty->name))); decls_scope->any_imports_failed = true; From 1ccbd1fb67898c0691c74e65a7b9786fb5698619 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 29 May 2019 16:31:49 -0400 Subject: [PATCH 3/3] `use` works on unions and enums in addition to structs --- src/analyze.cpp | 23 ++++++++++++----------- src/analyze.hpp | 1 + src/ir.cpp | 10 ++-------- test/compile_errors.zig | 2 +- 4 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 3731f3b94c..182bcc93a6 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3453,11 +3453,12 @@ TypeEnumField *find_enum_field_by_tag(ZigType *enum_type, const BigInt *tag) { } -static bool is_container(ZigType *type_entry) { +bool is_container(ZigType *type_entry) { switch (type_entry->id) { case ZigTypeIdInvalid: zig_unreachable(); case ZigTypeIdStruct: + return !type_entry->data.structure.is_slice; case ZigTypeIdEnum: case ZigTypeIdUnion: return true; @@ -3498,9 +3499,9 @@ bool is_array_ref(ZigType *type_entry) { return array->id == ZigTypeIdArray; } -bool is_container_ref(ZigType *type_entry) { - return is_ref(type_entry) ? - is_container(type_entry->data.pointer.child_type) : is_container(type_entry); +bool is_container_ref(ZigType *parent_ty) { + ZigType *ty = is_ref(parent_ty) ? parent_ty->data.pointer.child_type : parent_ty; + return is_slice(ty) || is_container(ty); } ZigType *container_ref_type(ZigType *type_entry) { @@ -3765,7 +3766,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { analyze_fn_ir(g, fn_table_entry, return_type_node); } -static void add_symbols_from_struct(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node, ScopeDecls* decls_scope) { +static void add_symbols_from_container(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node, ScopeDecls* decls_scope) { if (src_use_node->data.use.resolution == TldResolutionUnresolved) { preview_use_decl(g, src_use_node, decls_scope); } @@ -3784,9 +3785,9 @@ static void add_symbols_from_struct(CodeGen *g, AstNode *src_use_node, AstNode * ZigType *src_ty = use_expr->data.x_type; assert(src_ty); - if (src_ty->id != ZigTypeIdStruct || is_slice(src_ty)) { + if (!is_container(src_ty)) { add_node_error(g, dst_use_node, - buf_sprintf("expected struct, found '%s'", buf_ptr(&src_ty->name))); + buf_sprintf("expected struct, enum, or union; found '%s'", buf_ptr(&src_ty->name))); decls_scope->any_imports_failed = true; return; } @@ -3795,8 +3796,8 @@ static void add_symbols_from_struct(CodeGen *g, AstNode *src_use_node, AstNode * ScopeDecls *src_scope = get_container_scope(src_ty); // The top-level container where the symbols are defined, it's used in the // loop below in order to exclude the ones coming from an import statement - ZigType *src_import = get_scope_import(reinterpret_cast(src_scope)); - assert(src_import && src_import->id == ZigTypeIdStruct); + ZigType *src_import = get_scope_import(&src_scope->base); + assert(src_import != nullptr); if (src_scope->any_imports_failed) { decls_scope->any_imports_failed = true; @@ -3835,7 +3836,7 @@ static void add_symbols_from_struct(CodeGen *g, AstNode *src_use_node, AstNode * for (size_t i = 0; i < src_scope->use_decls.length; i += 1) { AstNode *use_decl_node = src_scope->use_decls.at(i); if (use_decl_node->data.use.visib_mod != VisibModPrivate) - add_symbols_from_struct(g, use_decl_node, dst_use_node, decls_scope); + add_symbols_from_container(g, use_decl_node, dst_use_node, decls_scope); } } @@ -3847,7 +3848,7 @@ void resolve_use_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) { { return; } - add_symbols_from_struct(g, node, node, decls_scope); + add_symbols_from_container(g, node, node, decls_scope); } void preview_use_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) { diff --git a/src/analyze.hpp b/src/analyze.hpp index a43b3063e0..d89bb91126 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -250,5 +250,6 @@ ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type); void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_path, bool translate_c); void src_assert(bool ok, AstNode *source_node); +bool is_container(ZigType *type_entry); #endif diff --git a/src/ir.cpp b/src/ir.cpp index 5d3cf5303c..fa60751ca5 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10266,12 +10266,6 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc return result; } -static bool is_container(ZigType *type) { - return type->id == ZigTypeIdStruct || - type->id == ZigTypeIdEnum || - type->id == ZigTypeIdUnion; -} - static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) { assert(old_bb); @@ -16179,7 +16173,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc if (type_is_invalid(container_type)) { return ira->codegen->invalid_instruction; - } else if (is_container_ref(container_type)) { + } else if (is_slice(container_type) || is_container_ref(container_type)) { assert(container_ptr->value.type->id == ZigTypeIdPointer); if (container_type->id == ZigTypeIdPointer) { ZigType *bare_type = container_ref_type(container_type); @@ -16249,7 +16243,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc if (type_is_invalid(child_type)) { return ira->codegen->invalid_instruction; - } else if (is_container(child_type) && !is_slice(child_type)) { + } else if (is_container(child_type)) { if (child_type->id == ZigTypeIdEnum) { if ((err = ensure_complete_type(ira->codegen, child_type))) return ira->codegen->invalid_instruction; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 7da5247d89..fbecacb94b 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -163,7 +163,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "usingnamespace with wrong type", \\use void; , - "tmp.zig:1:1: error: expected struct, found 'void'", + "tmp.zig:1:1: error: expected struct, enum, or union; found 'void'", ); cases.add(