Commit f1e5be9686
Changed files (6)
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) ",")
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,
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) {
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();
}
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");
+
}
//////////////////////////////////////////////////////////////////////////////
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;
+}