add peer type resolution []T and [0]T

closes #349

also fix slicing const array to be []const T instead of []T
This commit is contained in:
Andrew Kelley 2017-04-30 12:21:24 -04:00
parent 29defd705d
commit 43e7ac8418
4 changed files with 53 additions and 18 deletions

View File

@ -6218,16 +6218,18 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
convert_to_const_slice = true; convert_to_const_slice = true;
continue; continue;
} else if (cur_type->id == TypeTableEntryIdArray && is_slice(prev_type) && } else if (cur_type->id == TypeTableEntryIdArray && is_slice(prev_type) &&
prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const && (prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
types_match_const_cast_only(prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type, cur_type->data.array.len == 0) &&
cur_type->data.array.child_type)) types_match_const_cast_only(prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
cur_type->data.array.child_type))
{ {
convert_to_const_slice = false; convert_to_const_slice = false;
continue; continue;
} else if (prev_type->id == TypeTableEntryIdArray && is_slice(cur_type) && } else if (prev_type->id == TypeTableEntryIdArray && is_slice(cur_type) &&
cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const && (cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
types_match_const_cast_only(cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type, prev_type->data.array.len == 0) &&
prev_type->data.array.child_type)) types_match_const_cast_only(cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
prev_type->data.array.child_type))
{ {
prev_inst = cur_inst; prev_inst = cur_inst;
convert_to_const_slice = false; convert_to_const_slice = false;
@ -6796,8 +6798,9 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
if (!val) if (!val)
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
bool final_is_const = (value->value.type->id == TypeTableEntryIdMetaType) ? is_const : true;
return ir_get_const_ptr(ira, source_instruction, val, value->value.type, return ir_get_const_ptr(ira, source_instruction, val, value->value.type,
ConstPtrMutComptimeConst, is_const, is_volatile); ConstPtrMutComptimeConst, final_is_const, is_volatile);
} }
TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type, is_const, is_volatile, 0, 0); TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type, is_const, is_volatile, 0, 0);
@ -6806,6 +6809,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope, IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope,
source_instruction->source_node, value, is_const, is_volatile); source_instruction->source_node, value, is_const, is_volatile);
new_instruction->value.type = ptr_type; new_instruction->value.type = ptr_type;
new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;
fn_entry->alloca_list.append(new_instruction); fn_entry->alloca_list.append(new_instruction);
return new_instruction; return new_instruction;
} }

View File

@ -173,3 +173,25 @@ fn testCastZeroArrayToErrSliceMut() {
fn gimmeErrOrSlice() -> %[]u8 { fn gimmeErrOrSlice() -> %[]u8 {
return []u8{}; return []u8{};
} }
test "peer type resolution: [0]u8, []const u8, and %[]u8" {
{
var data = "hi";
const slice = data[0...];
assert((%%peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
assert((%%peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
}
comptime {
var data = "hi";
const slice = data[0...];
assert((%%peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
assert((%%peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
}
}
fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) -> %[]u8 {
if (a) {
return []u8{};
}
return slice[0...1];
}

View File

@ -486,3 +486,11 @@ test "volatileLoadAndStore" {
*ptr += 1; *ptr += 1;
assert(*ptr == 1235); assert(*ptr == 1235);
} }
test "slice string literal has type []const u8" {
comptime {
assert(@typeOf("aoeu"[0...]) == []const u8);
const array = []i32{1, 2, 3, 4};
assert(@typeOf(array[0...]) == []const i32);
}
}

View File

@ -5,7 +5,17 @@ const Node = struct {
children: []Node, children: []Node,
}; };
test "structContainsSliceOfItself" { test "struct contains slice of itself" {
var other_nodes = []Node{
Node {
.payload = 31,
.children = []Node{},
},
Node {
.payload = 32,
.children = []Node{},
},
};
var nodes = []Node { var nodes = []Node {
Node { Node {
.payload = 1, .payload = 1,
@ -17,16 +27,7 @@ test "structContainsSliceOfItself" {
}, },
Node { Node {
.payload = 3, .payload = 3,
.children = ([]Node{ .children = other_nodes[0...],
Node {
.payload = 31,
.children = []Node{},
},
Node {
.payload = 32,
.children = []Node{},
},
})[0...],
}, },
}; };
const root = Node { const root = Node {