diff --git a/doc/langref.html.in b/doc/langref.html.in index 38cbd63b2..1183e25c2 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -5733,19 +5733,19 @@ UseDecl = "use" Expression ";" ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";" -FnProto = option("nakedcc" | "stdcallcc" | "extern" | ("async" option("(" Expression ")"))) "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr +FnProto = option("nakedcc" | "stdcallcc" | "extern" | ("async" option("(" Expression ")"))) "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") (TypeExpr | "var") FnDef = option("inline" | "export") FnProto Block ParamDeclList = "(" list(ParamDecl, ",") ")" -ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "...") +ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "var" | "...") Block = option(Symbol ":") "{" many(Statement) "}" Statement = LocalVarDecl ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";" -TypeExpr = ErrorSetExpr | "var" +TypeExpr = ErrorSetExpr ErrorSetExpr = (PrefixOpExpression "!" PrefixOpExpression) | PrefixOpExpression diff --git a/src/all_types.hpp b/src/all_types.hpp index 72ec86055..6f36d34bf 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -16,6 +16,7 @@ #include "bigint.hpp" #include "bigfloat.hpp" #include "target.hpp" +#include "tokenizer.hpp" struct AstNode; struct ImportTableEntry; @@ -399,7 +400,6 @@ enum NodeType { NodeTypeStructValueField, NodeTypeArrayType, NodeTypeErrorType, - NodeTypeVarLiteral, NodeTypeIfErrorExpr, NodeTypeTestExpr, NodeTypeErrorSetDecl, @@ -427,6 +427,7 @@ struct AstNodeFnProto { Buf *name; ZigList params; AstNode *return_type; + Token *return_var_token; bool is_var_args; bool is_extern; bool is_export; @@ -456,6 +457,7 @@ struct AstNodeFnDecl { struct AstNodeParamDecl { Buf *name; AstNode *type; + Token *var_token; bool is_noalias; bool is_inline; bool is_var_args; @@ -866,9 +868,6 @@ struct AstNodeUnreachableExpr { struct AstNodeErrorType { }; -struct AstNodeVarLiteral { -}; - struct AstNodeAwaitExpr { AstNode *expr; }; @@ -933,7 +932,6 @@ struct AstNode { AstNodeUnreachableExpr unreachable_expr; AstNodeArrayType array_type; AstNodeErrorType error_type; - AstNodeVarLiteral var_literal; AstNodeErrorSetDecl err_set_decl; AstNodeCancelExpr cancel_expr; AstNodeResumeExpr resume_expr; @@ -1134,7 +1132,6 @@ struct TypeTableEntryPromise { enum TypeTableEntryId { TypeTableEntryIdInvalid, - TypeTableEntryIdVar, TypeTableEntryIdMetaType, TypeTableEntryIdVoid, TypeTableEntryIdBool, diff --git a/src/analyze.cpp b/src/analyze.cpp index fb7f04d6d..42bf2c8d4 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -200,7 +200,6 @@ static uint8_t bits_needed_for_unsigned(uint64_t x) { bool type_is_complete(TypeTableEntry *type_entry) { switch (type_entry->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: zig_unreachable(); case TypeTableEntryIdStruct: return type_entry->data.structure.complete; @@ -239,7 +238,6 @@ bool type_is_complete(TypeTableEntry *type_entry) { bool type_has_zero_bits_known(TypeTableEntry *type_entry) { switch (type_entry->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: zig_unreachable(); case TypeTableEntryIdStruct: return type_entry->data.structure.zero_bits_known; @@ -1281,7 +1279,6 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { switch (type_entry->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: zig_unreachable(); case TypeTableEntryIdMetaType: case TypeTableEntryIdUnreachable: @@ -1324,7 +1321,6 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) { switch (type_entry->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: zig_unreachable(); case TypeTableEntryIdMetaType: case TypeTableEntryIdNumLitFloat: @@ -1428,6 +1424,14 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c calling_convention_name(fn_type_id.cc))); return g->builtin_types.entry_invalid; } + } else if (param_node->data.param_decl.var_token != nullptr) { + if (!calling_convention_allows_zig_types(fn_type_id.cc)) { + add_node_error(g, param_node->data.param_decl.type, + buf_sprintf("parameter of type 'var' not allowed in function with calling convention '%s'", + calling_convention_name(fn_type_id.cc))); + return g->builtin_types.entry_invalid; + } + return get_generic_fn_type(g, &fn_type_id); } TypeTableEntry *type_entry = analyze_type_expr(g, child_scope, param_node->data.param_decl.type); @@ -1463,14 +1467,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c add_node_error(g, param_node->data.param_decl.type, buf_sprintf("parameter of type '%s' not allowed", buf_ptr(&type_entry->name))); return g->builtin_types.entry_invalid; - case TypeTableEntryIdVar: - if (!calling_convention_allows_zig_types(fn_type_id.cc)) { - add_node_error(g, param_node->data.param_decl.type, - buf_sprintf("parameter of type 'var' not allowed in function with calling convention '%s'", - calling_convention_name(fn_type_id.cc))); - return g->builtin_types.entry_invalid; - } - return get_generic_fn_type(g, &fn_type_id); case TypeTableEntryIdNumLitFloat: case TypeTableEntryIdNumLitInt: case TypeTableEntryIdNamespace: @@ -1527,6 +1523,16 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c fn_type_id.return_type = specified_return_type; } + if (fn_proto->return_var_token != nullptr) { + if (!calling_convention_allows_zig_types(fn_type_id.cc)) { + add_node_error(g, fn_proto->return_type, + buf_sprintf("return type 'var' not allowed in function with calling convention '%s'", + calling_convention_name(fn_type_id.cc))); + return g->builtin_types.entry_invalid; + } + return get_generic_fn_type(g, &fn_type_id); + } + if (!calling_convention_allows_zig_types(fn_type_id.cc) && !type_allowed_in_extern(g, fn_type_id.return_type)) { add_node_error(g, fn_proto->return_type, buf_sprintf("return type '%s' not allowed in function with calling convention '%s'", @@ -1552,7 +1558,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c case TypeTableEntryIdNamespace: case TypeTableEntryIdBlock: case TypeTableEntryIdBoundFn: - case TypeTableEntryIdVar: case TypeTableEntryIdMetaType: if (!calling_convention_allows_zig_types(fn_type_id.cc)) { add_node_error(g, fn_proto->return_type, @@ -3226,7 +3231,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { case NodeTypeStructValueField: case NodeTypeArrayType: case NodeTypeErrorType: - case NodeTypeVarLiteral: case NodeTypeIfErrorExpr: case NodeTypeTestExpr: case NodeTypeErrorSetDecl: @@ -3262,7 +3266,6 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt case TypeTableEntryIdInvalid: return g->builtin_types.entry_invalid; case TypeTableEntryIdUnreachable: - case TypeTableEntryIdVar: case TypeTableEntryIdNumLitFloat: case TypeTableEntryIdNumLitInt: case TypeTableEntryIdUndefLit: @@ -3641,7 +3644,6 @@ TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *t static bool is_container(TypeTableEntry *type_entry) { switch (type_entry->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: zig_unreachable(); case TypeTableEntryIdStruct: case TypeTableEntryIdEnum: @@ -3716,7 +3718,6 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) { case TypeTableEntryIdBlock: case TypeTableEntryIdBoundFn: case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: case TypeTableEntryIdArgTuple: case TypeTableEntryIdOpaque: case TypeTableEntryIdPromise: @@ -4216,7 +4217,6 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { case TypeTableEntryIdNamespace: case TypeTableEntryIdBlock: case TypeTableEntryIdBoundFn: - case TypeTableEntryIdVar: case TypeTableEntryIdArgTuple: case TypeTableEntryIdOpaque: zig_unreachable(); @@ -4515,7 +4515,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { case TypeTableEntryIdBoundFn: case TypeTableEntryIdInvalid: case TypeTableEntryIdUnreachable: - case TypeTableEntryIdVar: zig_unreachable(); } zig_unreachable(); @@ -4613,7 +4612,6 @@ bool type_has_bits(TypeTableEntry *type_entry) { bool type_requires_comptime(TypeTableEntry *type_entry) { switch (type_entry->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: case TypeTableEntryIdOpaque: zig_unreachable(); case TypeTableEntryIdNumLitFloat: @@ -5109,7 +5107,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { case TypeTableEntryIdBoundFn: case TypeTableEntryIdInvalid: case TypeTableEntryIdUnreachable: - case TypeTableEntryIdVar: case TypeTableEntryIdPromise: zig_unreachable(); } @@ -5189,9 +5186,6 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { case TypeTableEntryIdInvalid: buf_appendf(buf, "(invalid)"); return; - case TypeTableEntryIdVar: - buf_appendf(buf, "(var)"); - return; case TypeTableEntryIdVoid: buf_appendf(buf, "{}"); return; @@ -5427,7 +5421,6 @@ TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) uint32_t type_id_hash(TypeId x) { switch (x.id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: case TypeTableEntryIdOpaque: case TypeTableEntryIdMetaType: case TypeTableEntryIdVoid: @@ -5474,7 +5467,6 @@ bool type_id_eql(TypeId a, TypeId b) { return false; switch (a.id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: case TypeTableEntryIdMetaType: case TypeTableEntryIdVoid: case TypeTableEntryIdBool: @@ -5629,7 +5621,6 @@ size_t type_id_len() { size_t type_id_index(TypeTableEntryId id) { switch (id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: zig_unreachable(); case TypeTableEntryIdMetaType: return 0; @@ -5688,7 +5679,6 @@ size_t type_id_index(TypeTableEntryId id) { const char *type_id_name(TypeTableEntryId id) { switch (id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: zig_unreachable(); case TypeTableEntryIdMetaType: return "Type"; diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 6318ba3cf..ef1fe6e23 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -236,8 +236,6 @@ static const char *node_type_str(NodeType node_type) { return "ArrayType"; case NodeTypeErrorType: return "ErrorType"; - case NodeTypeVarLiteral: - return "VarLiteral"; case NodeTypeIfErrorExpr: return "IfErrorExpr"; case NodeTypeTestExpr: @@ -436,6 +434,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { } if (param_decl->data.param_decl.is_var_args) { fprintf(ar->f, "..."); + } else if (param_decl->data.param_decl.var_token != nullptr) { + fprintf(ar->f, "var"); } else { render_node_grouped(ar, param_decl->data.param_decl.type); } @@ -456,13 +456,17 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { fprintf(ar->f, ")"); } - AstNode *return_type_node = node->data.fn_proto.return_type; - assert(return_type_node != nullptr); - fprintf(ar->f, " "); - if (node->data.fn_proto.auto_err_set) { - fprintf(ar->f, "!"); + if (node->data.fn_proto.return_var_token != nullptr) { + fprintf(ar->f, "var"); + } else { + AstNode *return_type_node = node->data.fn_proto.return_type; + assert(return_type_node != nullptr); + fprintf(ar->f, " "); + if (node->data.fn_proto.auto_err_set) { + fprintf(ar->f, "!"); + } + render_node_grouped(ar, return_type_node); } - render_node_grouped(ar, return_type_node); break; } case NodeTypeFnDef: @@ -768,9 +772,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { case NodeTypeErrorType: fprintf(ar->f, "error"); break; - case NodeTypeVarLiteral: - fprintf(ar->f, "var"); - break; case NodeTypeAsmExpr: { AstNodeAsmExpr *asm_expr = &node->data.asm_expr; diff --git a/src/codegen.cpp b/src/codegen.cpp index 3aa8f6310..4a7b8f628 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4508,7 +4508,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con assert(!type_entry->zero_bits); switch (type_entry->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: case TypeTableEntryIdMetaType: case TypeTableEntryIdUnreachable: case TypeTableEntryIdNumLitFloat: @@ -4960,7 +4959,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c case TypeTableEntryIdNamespace: case TypeTableEntryIdBlock: case TypeTableEntryIdBoundFn: - case TypeTableEntryIdVar: case TypeTableEntryIdArgTuple: case TypeTableEntryIdOpaque: case TypeTableEntryIdPromise: @@ -5611,11 +5609,6 @@ static void define_builtin_types(CodeGen *g) { entry->zero_bits = true; g->builtin_types.entry_null = entry; } - { - TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVar); - buf_init_from_str(&entry->name, "(var)"); - g->builtin_types.entry_var = entry; - } { TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArgTuple); buf_init_from_str(&entry->name, "(args)"); @@ -6444,7 +6437,6 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry switch (type_entry->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: case TypeTableEntryIdMetaType: case TypeTableEntryIdNumLitFloat: case TypeTableEntryIdNumLitInt: @@ -6639,7 +6631,6 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf case TypeTableEntryIdNumLitInt: case TypeTableEntryIdUndefLit: case TypeTableEntryIdNullLit: - case TypeTableEntryIdVar: case TypeTableEntryIdArgTuple: case TypeTableEntryIdPromise: zig_unreachable(); @@ -6781,7 +6772,6 @@ static void gen_h_file(CodeGen *g) { TypeTableEntry *type_entry = gen_h->types_to_declare.at(type_i); switch (type_entry->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: case TypeTableEntryIdMetaType: case TypeTableEntryIdVoid: case TypeTableEntryIdBool: diff --git a/src/ir.cpp b/src/ir.cpp index 61f04fef3..6fc1322c3 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -2147,7 +2147,7 @@ static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *s size_t param_count = source_node->data.fn_proto.params.length; if (is_var_args) param_count -= 1; for (size_t i = 0; i < param_count; i += 1) { - ir_ref_instruction(param_types[i], irb->current_basic_block); + if (param_types[i] != nullptr) ir_ref_instruction(param_types[i], irb->current_basic_block); } if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); ir_ref_instruction(return_type, irb->current_basic_block); @@ -3305,12 +3305,6 @@ static IrInstruction *ir_gen_null_literal(IrBuilder *irb, Scope *scope, AstNode return ir_build_const_null(irb, scope, node); } -static IrInstruction *ir_gen_var_literal(IrBuilder *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeVarLiteral); - - return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_var); -} - static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { assert(node->type == NodeTypeSymbol); @@ -5916,11 +5910,15 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo is_var_args = true; break; } - AstNode *type_node = param_node->data.param_decl.type; - IrInstruction *type_value = ir_gen_node(irb, type_node, parent_scope); - if (type_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; - param_types[i] = type_value; + if (param_node->data.param_decl.var_token == nullptr) { + AstNode *type_node = param_node->data.param_decl.type; + IrInstruction *type_value = ir_gen_node(irb, type_node, parent_scope); + if (type_value == irb->codegen->invalid_instruction) + return irb->codegen->invalid_instruction; + param_types[i] = type_value; + } else { + param_types[i] = nullptr; + } } IrInstruction *align_value = nullptr; @@ -5931,12 +5929,16 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo } IrInstruction *return_type; - if (node->data.fn_proto.return_type == nullptr) { - return_type = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_void); + if (node->data.fn_proto.return_var_token == nullptr) { + if (node->data.fn_proto.return_type == nullptr) { + return_type = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_void); + } else { + return_type = ir_gen_node(irb, node->data.fn_proto.return_type, parent_scope); + if (return_type == irb->codegen->invalid_instruction) + return irb->codegen->invalid_instruction; + } } else { - return_type = ir_gen_node(irb, node->data.fn_proto.return_type, parent_scope); - if (return_type == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + return_type = nullptr; } return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, return_type, is_var_args); @@ -6189,8 +6191,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval); case NodeTypeNullLiteral: return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval); - case NodeTypeVarLiteral: - return ir_lval_wrap(irb, scope, ir_gen_var_literal(irb, scope, node), lval); case NodeTypeIfErrorExpr: return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval); case NodeTypeTestExpr: @@ -7515,11 +7515,6 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, return ImplicitCastMatchResultReportedError; } - // implicit conversion from anything to var - if (expected_type->id == TypeTableEntryIdVar) { - return ImplicitCastMatchResultYes; - } - // implicit conversion from non maybe type to maybe type if (expected_type->id == TypeTableEntryIdMaybe && ir_types_match_with_implicit_cast(ira, expected_type->data.maybe.child_type, actual_type, value)) @@ -9341,9 +9336,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst return ira->codegen->invalid_instruction; } - if (wanted_type->id == TypeTableEntryIdVar) - return value; - // explicit match or non-const to const if (types_match_const_cast_only(ira, wanted_type, actual_type, source_node).id == ConstCastResultIdOk) { return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false); @@ -10311,9 +10303,6 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp ir_add_error_node(ira, source_node, buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); return ira->codegen->builtin_types.entry_invalid; - - case TypeTableEntryIdVar: - zig_unreachable(); } IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, resolved_type); @@ -11106,7 +11095,6 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) { case TypeTableEntryIdInvalid: zig_unreachable(); case TypeTableEntryIdUnreachable: - case TypeTableEntryIdVar: return VarClassRequiredIllegal; case TypeTableEntryIdBool: case TypeTableEntryIdInt: @@ -11279,7 +11267,6 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi switch (target->value.type->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: case TypeTableEntryIdUnreachable: zig_unreachable(); case TypeTableEntryIdFn: { @@ -11332,7 +11319,6 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi TypeTableEntry *type_value = target->value.data.x_type; switch (type_value->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: zig_unreachable(); case TypeTableEntryIdStruct: if (is_slice(type_value)) { @@ -11543,14 +11529,20 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node { AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(*next_proto_i); assert(param_decl_node->type == NodeTypeParamDecl); - AstNode *param_type_node = param_decl_node->data.param_decl.type; - TypeTableEntry *param_type = analyze_type_expr(ira->codegen, *exec_scope, param_type_node); - if (type_is_invalid(param_type)) - return false; - IrInstruction *casted_arg = ir_implicit_cast(ira, arg, param_type); - if (type_is_invalid(casted_arg->value.type)) - return false; + IrInstruction *casted_arg; + if (param_decl_node->data.param_decl.var_token == nullptr) { + AstNode *param_type_node = param_decl_node->data.param_decl.type; + TypeTableEntry *param_type = analyze_type_expr(ira->codegen, *exec_scope, param_type_node); + if (type_is_invalid(param_type)) + return false; + + casted_arg = ir_implicit_cast(ira, arg, param_type); + if (type_is_invalid(casted_arg->value.type)) + return false; + } else { + casted_arg = arg; + } ConstExprValue *arg_val = ir_resolve_const(ira, casted_arg, UndefBad); if (!arg_val) @@ -11579,19 +11571,18 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod arg_part_of_generic_id = true; casted_arg = ir_implicit_byval_const_ref_cast(ira, arg); } else { - AstNode *param_type_node = param_decl_node->data.param_decl.type; - TypeTableEntry *param_type = analyze_type_expr(ira->codegen, *child_scope, param_type_node); - if (type_is_invalid(param_type)) - return false; + if (param_decl_node->data.param_decl.var_token == nullptr) { + AstNode *param_type_node = param_decl_node->data.param_decl.type; + TypeTableEntry *param_type = analyze_type_expr(ira->codegen, *child_scope, param_type_node); + if (type_is_invalid(param_type)) + return false; - bool is_var_type = (param_type->id == TypeTableEntryIdVar); - if (is_var_type) { - arg_part_of_generic_id = true; - casted_arg = ir_implicit_byval_const_ref_cast(ira, arg); - } else { casted_arg = ir_implicit_cast(ira, arg, param_type); if (type_is_invalid(casted_arg->value.type)) return false; + } else { + arg_part_of_generic_id = true; + casted_arg = ir_implicit_byval_const_ref_cast(ira, arg); } } @@ -12304,7 +12295,6 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op return ira->codegen->builtin_types.entry_invalid; switch (type_entry->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: zig_unreachable(); case TypeTableEntryIdMetaType: case TypeTableEntryIdVoid: @@ -13539,10 +13529,6 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi switch (type_entry->id) { case TypeTableEntryIdInvalid: zig_unreachable(); // handled above - case TypeTableEntryIdVar: - ir_add_error_node(ira, expr_value->source_node, - buf_sprintf("type '%s' not eligible for @typeOf", buf_ptr(&type_entry->name))); - return ira->codegen->builtin_types.entry_invalid; case TypeTableEntryIdNumLitFloat: case TypeTableEntryIdNumLitInt: case TypeTableEntryIdUndefLit: @@ -13807,7 +13793,6 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, switch (child_type->id) { case TypeTableEntryIdInvalid: // handled above zig_unreachable(); - case TypeTableEntryIdVar: case TypeTableEntryIdUnreachable: case TypeTableEntryIdUndefLit: case TypeTableEntryIdNullLit: @@ -13916,7 +13901,6 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira, switch (child_type->id) { case TypeTableEntryIdInvalid: // handled above zig_unreachable(); - case TypeTableEntryIdVar: case TypeTableEntryIdUnreachable: case TypeTableEntryIdUndefLit: case TypeTableEntryIdNullLit: @@ -13968,7 +13952,6 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira, switch (type_entry->id) { case TypeTableEntryIdInvalid: // handled above zig_unreachable(); - case TypeTableEntryIdVar: case TypeTableEntryIdUnreachable: case TypeTableEntryIdUndefLit: case TypeTableEntryIdNullLit: @@ -14316,7 +14299,6 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, switch (target_type->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: zig_unreachable(); case TypeTableEntryIdMetaType: case TypeTableEntryIdVoid: @@ -14911,7 +14893,6 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_ } case TypeTableEntryIdEnum: zig_panic("TODO min/max value for enum type"); - case TypeTableEntryIdVar: case TypeTableEntryIdMetaType: case TypeTableEntryIdUnreachable: case TypeTableEntryIdPointer: @@ -16159,7 +16140,6 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc switch (type_entry->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: zig_unreachable(); case TypeTableEntryIdMetaType: case TypeTableEntryIdUnreachable: @@ -16461,21 +16441,23 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc zig_unreachable(); } } - IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->other; - if (type_is_invalid(param_type_value->value.type)) - return ira->codegen->builtin_types.entry_invalid; - FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index]; param_info->is_noalias = param_node->data.param_decl.is_noalias; - param_info->type = ir_resolve_type(ira, param_type_value); - if (type_is_invalid(param_info->type)) - return ira->codegen->builtin_types.entry_invalid; - if (param_info->type->id == TypeTableEntryIdVar) { + if (instruction->param_types[fn_type_id.next_param_index] == nullptr) { + param_info->type = nullptr; ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); out_val->data.x_type = get_generic_fn_type(ira->codegen, &fn_type_id); return ira->codegen->builtin_types.entry_type; + } else { + IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->other; + if (type_is_invalid(param_type_value->value.type)) + return ira->codegen->builtin_types.entry_invalid; + param_info->type = ir_resolve_type(ira, param_type_value); + if (type_is_invalid(param_info->type)) + return ira->codegen->builtin_types.entry_invalid; } + } if (instruction->align_value != nullptr) { @@ -16869,7 +16851,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue assert(val->special == ConstValSpecialStatic); switch (val->type->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: case TypeTableEntryIdMetaType: case TypeTableEntryIdOpaque: case TypeTableEntryIdBoundFn: @@ -16937,7 +16918,6 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue assert(val->special == ConstValSpecialStatic); switch (val->type->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: case TypeTableEntryIdMetaType: case TypeTableEntryIdOpaque: case TypeTableEntryIdBoundFn: @@ -17014,7 +16994,6 @@ static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruc switch (src_type->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: case TypeTableEntryIdMetaType: case TypeTableEntryIdOpaque: case TypeTableEntryIdBoundFn: @@ -17041,7 +17020,6 @@ static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruc switch (dest_type->id) { case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: case TypeTableEntryIdMetaType: case TypeTableEntryIdOpaque: case TypeTableEntryIdBoundFn: diff --git a/src/parser.cpp b/src/parser.cpp index 38994c79f..738d19a1c 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -263,21 +263,14 @@ static AstNode *ast_parse_error_set_expr(ParseContext *pc, size_t *token_index, } /* -TypeExpr = ErrorSetExpr | "var" +TypeExpr = ErrorSetExpr */ static AstNode *ast_parse_type_expr(ParseContext *pc, size_t *token_index, bool mandatory) { - Token *token = &pc->tokens->at(*token_index); - if (token->id == TokenIdKeywordVar) { - AstNode *node = ast_create_node(pc, NodeTypeVarLiteral, token); - *token_index += 1; - return node; - } else { - return ast_parse_error_set_expr(pc, token_index, mandatory); - } + return ast_parse_error_set_expr(pc, token_index, mandatory); } /* -ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "...") +ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "var" | "...") */ static AstNode *ast_parse_param_decl(ParseContext *pc, size_t *token_index) { Token *token = &pc->tokens->at(*token_index); @@ -308,6 +301,9 @@ static AstNode *ast_parse_param_decl(ParseContext *pc, size_t *token_index) { if (ellipsis_tok->id == TokenIdEllipsis3) { *token_index += 1; node->data.param_decl.is_var_args = true; + } else if (ellipsis_tok->id == TokenIdKeywordVar) { + *token_index += 1; + node->data.param_decl.var_token = ellipsis_tok; } else { node->data.param_decl.type = ast_parse_type_expr(pc, token_index, true); } @@ -2421,7 +2417,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand } /* -FnProto = option("nakedcc" | "stdcallcc" | "extern" | ("async" option("(" Expression ")"))) "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr +FnProto = option("nakedcc" | "stdcallcc" | "extern" | ("async" option("(" Expression ")"))) "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") (TypeExpr | "var") */ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { Token *first_token = &pc->tokens->at(*token_index); @@ -2507,19 +2503,25 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m ast_eat_token(pc, token_index, TokenIdRParen); next_token = &pc->tokens->at(*token_index); } - if (next_token->id == TokenIdKeywordError) { - Token *maybe_lbrace_tok = &pc->tokens->at(*token_index + 1); - if (maybe_lbrace_tok->id == TokenIdLBrace) { - *token_index += 1; - node->data.fn_proto.return_type = ast_create_node(pc, NodeTypeErrorType, next_token); - return node; - } - } else if (next_token->id == TokenIdBang) { + if (next_token->id == TokenIdKeywordVar) { + node->data.fn_proto.return_var_token = next_token; *token_index += 1; - node->data.fn_proto.auto_err_set = true; next_token = &pc->tokens->at(*token_index); + } else { + if (next_token->id == TokenIdKeywordError) { + Token *maybe_lbrace_tok = &pc->tokens->at(*token_index + 1); + if (maybe_lbrace_tok->id == TokenIdLBrace) { + *token_index += 1; + node->data.fn_proto.return_type = ast_create_node(pc, NodeTypeErrorType, next_token); + return node; + } + } else if (next_token->id == TokenIdBang) { + *token_index += 1; + node->data.fn_proto.auto_err_set = true; + next_token = &pc->tokens->at(*token_index); + } + node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, true); } - node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, true); return node; } @@ -3069,9 +3071,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont case NodeTypeErrorType: // none break; - case NodeTypeVarLiteral: - // none - break; case NodeTypeAddrOfExpr: visit_field(&node->data.addr_of_expr.align_expr, visit, context); visit_field(&node->data.addr_of_expr.op_expr, visit, context); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 61234864b..0ad678755 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1,6 +1,13 @@ const tests = @import("tests.zig"); pub fn addCases(cases: &tests.CompileErrorContext) void { + cases.add("var not allowed in structs", + \\export fn entry() void { + \\ var s = (struct{v: var}){.v=i32(10)}; + \\} + , + ".tmp_source.zig:2:23: error: invalid token: 'var'"); + cases.add("@ptrCast discards const qualifier", \\export fn entry() void { \\ const x: i32 = 1234;