diff --git a/doc/langref.md b/doc/langref.md index d43feb27c3..50994ecbb9 100644 --- a/doc/langref.md +++ b/doc/langref.md @@ -17,7 +17,7 @@ VariableDeclaration = ("var" | "const") "Symbol" option(":" TypeExpr) "=" Expres ContainerDecl = ("struct" | "enum" | "union") "Symbol" option(ParamDeclList) "{" many(StructMember) "}" -StructMember = many(Directive) option(VisibleMod) (StructField | FnDef | GlobalVarDecl) +StructMember = many(Directive) option(VisibleMod) (StructField | FnDef | GlobalVarDecl | ContainerDecl) StructField = "Symbol" option(":" Expression) ",") diff --git a/src/analyze.cpp b/src/analyze.cpp index ac26cb3980..1d951f867e 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -5217,7 +5217,7 @@ static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *imp AstNode **generic_param_type_node = &generic_param_decl_node->data.param_decl.type; TypeTableEntry *expected_param_type = analyze_type_expr(g, decl_node->owner, - decl_node->owner->block_context, *generic_param_type_node); + child_context, *generic_param_type_node); if (expected_param_type->id == TypeTableEntryIdInvalid) { return expected_param_type; } @@ -5809,6 +5809,17 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, if (resolved_type->id == TypeTableEntryIdInvalid) { return resolved_type; } else if (resolved_type->id == TypeTableEntryIdErrorUnion) { + TypeTableEntry *return_type = context->fn_entry->type_entry->data.fn.fn_type_id.return_type; + if (return_type->id != TypeTableEntryIdErrorUnion && + return_type->id != TypeTableEntryIdPureError) + { + ErrorMsg *msg = add_node_error(g, node, + buf_sprintf("%%return statement in function with return type '%s'", + buf_ptr(&return_type->name))); + AstNode *return_type_node = context->fn_entry->fn_def_node->data.fn_def.fn_proto->data.fn_proto.return_type; + add_error_note(g, msg, return_type_node, buf_sprintf("function return type here")); + } + return resolved_type->data.error.child_type; } else { add_node_error(g, node->data.return_expr.expr, diff --git a/src/parser.cpp b/src/parser.cpp index 9a85dc3b9e..943bd2c58d 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2605,7 +2605,7 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index, /* ContainerDecl = ("struct" | "enum" | "union") "Symbol" option(ParamDeclList) "{" many(StructMember) "}" -StructMember = many(Directive) option(VisibleMod) (StructField | FnDef | GlobalVarDecl) +StructMember = many(Directive) option(VisibleMod) (StructField | FnDef | GlobalVarDecl | ContainerDecl) StructField : "Symbol" option(":" Expression) ",") */ static AstNode *ast_parse_container_decl(ParseContext *pc, int *token_index, @@ -2675,6 +2675,12 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, int *token_index, continue; } + AstNode *container_decl_node = ast_parse_container_decl(pc, token_index, directive_list, visib_mod); + if (container_decl_node) { + node->data.struct_decl.decls.append(container_decl_node); + continue; + } + Token *token = &pc->tokens->at(*token_index); if (token->id == TokenIdRBrace) { diff --git a/std/hash_map.zig b/std/hash_map.zig index 74efc74363..0191b0f5e8 100644 --- a/std/hash_map.zig +++ b/std/hash_map.zig @@ -47,7 +47,7 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- } unreachable{} // no next item } - }; + } pub fn init(hm: &Self, allocator: &Allocator, capacity: isize) { assert(capacity > 0); @@ -56,7 +56,7 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- } pub fn deinit(hm: &Self) { - free(_entries); + hm.allocator.free(hm.allocator, ([]u8)(hm.entries)); } pub fn clear(hm: &Self) { @@ -128,8 +128,7 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- } fn init_capacity(hm: &Self, capacity: isize) { - hm.capacity = capacity; - hm.entries = ([]Entry)(hm.allocator.alloc(hm.allocator, capacity * @sizeof(Entry))); + hm.entries = ([]Entry)(%return hm.allocator.alloc(hm.allocator, capacity * @sizeof(Entry))); hm.size = 0; hm.max_distance_from_start_index = 0; for (hm.entries) |*entry| { @@ -143,7 +142,7 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- } } - fn internal_put(hm: &Self, K orig_key, V orig_value) { + fn internal_put(hm: &Self, orig_key: K, orig_value: V) { var key = orig_key; var value = orig_value; const start_index = key_to_index(key); @@ -179,7 +178,7 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- } hm.max_distance_from_start_index = math.max(isize)(distance_from_start_index, hm.max_distance_from_start_index); - *entry = { + *entry = Entry { .used = true, .distance_from_start_index = distance_from_start_index, .key = key, @@ -202,21 +201,6 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- return null; } - Entry *internal_get(const K &key) const { - int start_index = key_to_index(key); - for (int roll_over = 0; roll_over <= _max_distance_from_start_index; roll_over += 1) { - int index = (start_index + roll_over) % _capacity; - Entry *entry = &_entries[index]; - - if (!entry->used) - return NULL; - - if (EqualFn(entry->key, key)) - return entry; - } - return NULL; - } - fn key_to_index(hm: &Self, key: K) -> isize { return isize(hash(key)) % hm.entries.len; } @@ -249,7 +233,7 @@ fn global_free(self: &Allocator, old_mem: []u8) { #attribute("test") fn basic_hash_map_test() { - var map: HashMap(i32, i32, hash_i32, eql_i32); + var map: HashMap(i32, i32, hash_i32, eql_i32) = undefined; map.init(&global_allocator, 4); defer map.deinit(); } diff --git a/test/run_tests.cpp b/test/run_tests.cpp index aee5fe17fe..d927e743c8 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -1382,6 +1382,15 @@ fn f() { } )SOURCE", 1, ".tmp_source.zig:4:19: error: type 'i8' has same or fewer bits than destination type 'i8'"); + add_compile_fail_case("truncate same bit count", R"SOURCE( +fn f() { + %return something(); +} +fn something() -> %void { } + )SOURCE", 2, + ".tmp_source.zig:3:5: error: %return statement in function with return type 'void'", + ".tmp_source.zig:2:8: note: function return type here"); + } ////////////////////////////////////////////////////////////////////////////// diff --git a/test/self_hosted.zig b/test/self_hosted.zig index 2c1b462334..9843ced9ae 100644 --- a/test/self_hosted.zig +++ b/test/self_hosted.zig @@ -1648,3 +1648,11 @@ fn const_decls_in_struct() { struct GenericDataThing(count: isize) { const count_plus_one = count + 1; } + +#attribute("test") +fn use_generic_param_in_generic_param() { + assert(a_generic_fn(i32, 3)(4) == 7); +} +fn a_generic_fn(T: type, a: T)(b: T) -> T { + return a + b; +}