| ... | ... | @@ -49,6 +49,7 @@ static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); |
| 49 | 49 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval); |
| 50 | 50 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); |
| 51 | 51 | static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type); |
| 52 | static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr); |
| 52 | 53 | |
| 53 | 54 | ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) { |
| 54 | 55 | assert(const_val->type->id == TypeTableEntryIdPointer); |
| ... | ... | @@ -6292,7 +6293,26 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, |
| 6292 | 6293 | } |
| 6293 | 6294 | } |
| 6294 | 6295 | |
| 6295 | | // implicit [N]T to &const []const N |
| 6296 | // implicit &const [N]T to []const T |
| 6297 | if (expected_type->id == TypeTableEntryIdStruct && |
| 6298 | expected_type->data.structure.is_slice && |
| 6299 | actual_type->id == TypeTableEntryIdPointer && |
| 6300 | actual_type->data.pointer.is_const && |
| 6301 | actual_type->data.pointer.child_type->id == TypeTableEntryIdArray) |
| 6302 | { |
| 6303 | TypeTableEntry *ptr_type = expected_type->data.structure.fields[slice_ptr_index].type_entry; |
| 6304 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 6305 | |
| 6306 | TypeTableEntry *array_type = actual_type->data.pointer.child_type; |
| 6307 | |
| 6308 | if ((ptr_type->data.pointer.is_const || array_type->data.array.len == 0) && |
| 6309 | types_match_const_cast_only(ptr_type->data.pointer.child_type, array_type->data.array.child_type)) |
| 6310 | { |
| 6311 | return ImplicitCastMatchResultYes; |
| 6312 | } |
| 6313 | } |
| 6314 | |
| 6315 | // implicit [N]T to &const []const T |
| 6296 | 6316 | if (expected_type->id == TypeTableEntryIdPointer && |
| 6297 | 6317 | expected_type->data.pointer.is_const && |
| 6298 | 6318 | is_slice(expected_type->data.pointer.child_type) && |
| ... | ... | @@ -6308,7 +6328,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, |
| 6308 | 6328 | } |
| 6309 | 6329 | } |
| 6310 | 6330 | |
| 6311 | | // implicit [N]T to ?[]const N |
| 6331 | // implicit [N]T to ?[]const T |
| 6312 | 6332 | if (expected_type->id == TypeTableEntryIdMaybe && |
| 6313 | 6333 | is_slice(expected_type->data.maybe.child_type) && |
| 6314 | 6334 | actual_type->id == TypeTableEntryIdArray) |
| ... | ... | @@ -7069,12 +7089,20 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi |
| 7069 | 7089 | } |
| 7070 | 7090 | |
| 7071 | 7091 | static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr, |
| 7072 | | IrInstruction *array, TypeTableEntry *wanted_type) |
| 7092 | IrInstruction *array_arg, TypeTableEntry *wanted_type) |
| 7073 | 7093 | { |
| 7074 | 7094 | assert(is_slice(wanted_type)); |
| 7075 | 7095 | // In this function we honor the const-ness of wanted_type, because |
| 7076 | 7096 | // we may be casting [0]T to []const T which is perfectly valid. |
| 7077 | 7097 | |
| 7098 | IrInstruction *array_ptr = nullptr; |
| 7099 | IrInstruction *array; |
| 7100 | if (array_arg->value.type->id == TypeTableEntryIdPointer) { |
| 7101 | array = ir_get_deref(ira, source_instr, array_arg); |
| 7102 | array_ptr = array_arg; |
| 7103 | } else { |
| 7104 | array = array_arg; |
| 7105 | } |
| 7078 | 7106 | TypeTableEntry *array_type = array->value.type; |
| 7079 | 7107 | assert(array_type->id == TypeTableEntryIdArray); |
| 7080 | 7108 | |
| ... | ... | @@ -7094,7 +7122,7 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s |
| 7094 | 7122 | source_instr->source_node, ira->codegen->builtin_types.entry_usize); |
| 7095 | 7123 | init_const_usize(ira->codegen, &end->value, array_type->data.array.len); |
| 7096 | 7124 | |
| 7097 | | IrInstruction *array_ptr = ir_get_ref(ira, source_instr, array, true, false); |
| 7125 | if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false); |
| 7098 | 7126 | |
| 7099 | 7127 | IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope, |
| 7100 | 7128 | source_instr->source_node, array_ptr, start, end, false); |
| ... | ... | @@ -7374,6 +7402,24 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 7374 | 7402 | } |
| 7375 | 7403 | } |
| 7376 | 7404 | |
| 7405 | // expliict cast from &const [N]T to []const T |
| 7406 | if (is_slice(wanted_type) && |
| 7407 | actual_type->id == TypeTableEntryIdPointer && |
| 7408 | actual_type->data.pointer.is_const && |
| 7409 | actual_type->data.pointer.child_type->id == TypeTableEntryIdArray) |
| 7410 | { |
| 7411 | TypeTableEntry *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; |
| 7412 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 7413 | |
| 7414 | TypeTableEntry *array_type = actual_type->data.pointer.child_type; |
| 7415 | |
| 7416 | if ((ptr_type->data.pointer.is_const || array_type->data.array.len == 0) && |
| 7417 | types_match_const_cast_only(ptr_type->data.pointer.child_type, array_type->data.array.child_type)) |
| 7418 | { |
| 7419 | return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type); |
| 7420 | } |
| 7421 | } |
| 7422 | |
| 7377 | 7423 | // explicit cast from [N]T to &const []const N |
| 7378 | 7424 | if (wanted_type->id == TypeTableEntryIdPointer && |
| 7379 | 7425 | wanted_type->data.pointer.is_const && |
| ... | ... | @@ -7674,6 +7720,13 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ |
| 7674 | 7720 | zig_unreachable(); |
| 7675 | 7721 | } |
| 7676 | 7722 | |
| 7723 | static IrInstruction *ir_implicit_byval_const_ref_cast(IrAnalyze *ira, IrInstruction *inst) { |
| 7724 | if (type_is_copyable(ira->codegen, inst->value.type)) |
| 7725 | return inst; |
| 7726 | TypeTableEntry *const_ref_type = get_pointer_to_type(ira->codegen, inst->value.type, true); |
| 7727 | return ir_implicit_cast(ira, inst, const_ref_type); |
| 7728 | } |
| 7729 | |
| 7677 | 7730 | static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) { |
| 7678 | 7731 | TypeTableEntry *type_entry = ptr->value.type; |
| 7679 | 7732 | if (type_is_invalid(type_entry)) { |
| ... | ... | @@ -8816,7 +8869,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod |
| 8816 | 8869 | IrInstruction *casted_arg; |
| 8817 | 8870 | if (is_var_args) { |
| 8818 | 8871 | arg_part_of_generic_id = true; |
| 8819 | | casted_arg = arg; |
| 8872 | casted_arg = ir_implicit_byval_const_ref_cast(ira, arg); |
| 8820 | 8873 | } else { |
| 8821 | 8874 | AstNode *param_type_node = param_decl_node->data.param_decl.type; |
| 8822 | 8875 | TypeTableEntry *param_type = analyze_type_expr(ira->codegen, *child_scope, param_type_node); |
| ... | ... | @@ -8826,7 +8879,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod |
| 8826 | 8879 | bool is_var_type = (param_type->id == TypeTableEntryIdVar); |
| 8827 | 8880 | if (is_var_type) { |
| 8828 | 8881 | arg_part_of_generic_id = true; |
| 8829 | | casted_arg = arg; |
| 8882 | casted_arg = ir_implicit_byval_const_ref_cast(ira, arg); |
| 8830 | 8883 | } else { |
| 8831 | 8884 | casted_arg = ir_implicit_cast(ira, arg, param_type); |
| 8832 | 8885 | if (type_is_invalid(casted_arg->value.type)) |