diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-04-07 17:56:01 -0400 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-04-07 17:56:01 -0400 |
| commit | 7611ed3484ad810fe10d3c303a04d66bfa0bd6fd (patch) | |
| tree | dc0b432b5abc0b0cb46e917f2fa30ae99e4ba515 /src/ir.cpp | |
| parent | 5eb78ba1772b54af1ecfb1cd28cb0f1c46dab9b3 (diff) | |
| download | zig-7611ed3484ad810fe10d3c303a04d66bfa0bd6fd.tar.gz zig-7611ed3484ad810fe10d3c303a04d66bfa0bd6fd.zip | |
allow implicit cast from `[N]T` to `&const []const T`
closes #296
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 625bff3b38..b3f647db70 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -5751,6 +5751,10 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc return false; } +static bool is_slice(TypeTableEntry *type) { + return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice; +} + enum ImplicitCastMatchResult { ImplicitCastMatchResultNo, ImplicitCastMatchResultYes, @@ -5837,6 +5841,22 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, } } + // implicit [N]T to &const []const N + if (expected_type->id == TypeTableEntryIdPointer && + expected_type->data.pointer.is_const && + is_slice(expected_type->data.pointer.child_type) && + actual_type->id == TypeTableEntryIdArray) + { + TypeTableEntry *ptr_type = + expected_type->data.pointer.child_type->data.structure.fields[slice_ptr_index].type_entry; + assert(ptr_type->id == TypeTableEntryIdPointer); + if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) && + types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type)) + { + return ImplicitCastMatchResultYes; + } + } + // implicit number literal to typed number // implicit number literal to &const integer if (actual_type->id == TypeTableEntryIdNumLitFloat || @@ -5883,10 +5903,6 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, return ImplicitCastMatchResultNo; } -static bool is_slice(TypeTableEntry *type) { - return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice; -} - static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, IrInstruction **instructions, size_t instruction_count) { assert(instruction_count >= 1); IrInstruction *prev_inst = instructions[0]; @@ -6860,6 +6876,30 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst } } + // explicit cast from [N]T to &const []const N + if (wanted_type->id == TypeTableEntryIdPointer && + wanted_type->data.pointer.is_const && + is_slice(wanted_type->data.pointer.child_type) && + actual_type->id == TypeTableEntryIdArray) + { + TypeTableEntry *ptr_type = + wanted_type->data.pointer.child_type->data.structure.fields[slice_ptr_index].type_entry; + assert(ptr_type->id == TypeTableEntryIdPointer); + if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) && + types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type)) + { + IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.pointer.child_type, value); + if (type_is_invalid(cast1->value.type)) + return ira->codegen->invalid_instruction; + + IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1); + if (type_is_invalid(cast2->value.type)) + return ira->codegen->invalid_instruction; + + return cast2; + } + } + // explicit cast from []T to []u8 or []u8 to []T if (is_slice(wanted_type) && is_slice(actual_type) && (is_u8(wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type) || |
