authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-22 12:19:20-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-22 12:19:20-04:00
logaafb0b90822e55135e1c50962768e54e6c62b164
treea67fa2d4c85969c526eab919e0d9f99bd4dc0586
parent1a0081b763d145de8a89ab94aca400daa5666dac

slicing now returns correct const-ness

also remove the ability to override constness when slicing closes #334

8 files changed, 44 insertions(+), 29 deletions(-)

doc/langref.md+1-1
...@@ -133,7 +133,7 @@ FnCallExpression = "(" list(Expression, ",") ")"...@@ -133,7 +133,7 @@ FnCallExpression = "(" list(Expression, ",") ")"
133133
134ArrayAccessExpression = "[" Expression "]"134ArrayAccessExpression = "[" Expression "]"
135135
136SliceExpression = "[" Expression "..." option(Expression) "]" option("const")136SliceExpression = "[" Expression "..." option(Expression) "]"
137137
138ContainerInitExpression = "{" ContainerInitBody "}"138ContainerInitExpression = "{" ContainerInitBody "}"
139139
src/all_types.hpp-2
...@@ -532,7 +532,6 @@ struct AstNodeSliceExpr {...@@ -532,7 +532,6 @@ struct AstNodeSliceExpr {
532 AstNode *array_ref_expr;532 AstNode *array_ref_expr;
533 AstNode *start;533 AstNode *start;
534 AstNode *end;534 AstNode *end;
535 bool is_const;
536};535};
537536
538struct AstNodeFieldAccessExpr {537struct AstNodeFieldAccessExpr {
...@@ -2260,7 +2259,6 @@ struct IrInstructionSlice {...@@ -2260,7 +2259,6 @@ struct IrInstructionSlice {
2260 IrInstruction *ptr;2259 IrInstruction *ptr;
2261 IrInstruction *start;2260 IrInstruction *start;
2262 IrInstruction *end;2261 IrInstruction *end;
2263 bool is_const;
2264 bool safety_check_on;2262 bool safety_check_on;
2265 LLVMValueRef tmp_ptr;2263 LLVMValueRef tmp_ptr;
2266};2264};
src/ast_render.cpp-2
...@@ -894,8 +894,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -894,8 +894,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
894 if (node->data.slice_expr.end)894 if (node->data.slice_expr.end)
895 render_node_grouped(ar, node->data.slice_expr.end);895 render_node_grouped(ar, node->data.slice_expr.end);
896 fprintf(ar->f, "]");896 fprintf(ar->f, "]");
897 if (node->data.slice_expr.is_const)
898 fprintf(ar->f, "const");
899 break;897 break;
900 }898 }
901 case NodeTypeUnwrapErrorExpr:899 case NodeTypeUnwrapErrorExpr:
src/ir.cpp+19-14
...@@ -1729,13 +1729,12 @@ static IrInstruction *ir_build_memcpy_from(IrBuilder *irb, IrInstruction *old_in...@@ -1729,13 +1729,12 @@ static IrInstruction *ir_build_memcpy_from(IrBuilder *irb, IrInstruction *old_in
1729}1729}
17301730
1731static IrInstruction *ir_build_slice(IrBuilder *irb, Scope *scope, AstNode *source_node,1731static IrInstruction *ir_build_slice(IrBuilder *irb, Scope *scope, AstNode *source_node,
1732 IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool is_const, bool safety_check_on)1732 IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on)
1733{1733{
1734 IrInstructionSlice *instruction = ir_build_instruction<IrInstructionSlice>(irb, scope, source_node);1734 IrInstructionSlice *instruction = ir_build_instruction<IrInstructionSlice>(irb, scope, source_node);
1735 instruction->ptr = ptr;1735 instruction->ptr = ptr;
1736 instruction->start = start;1736 instruction->start = start;
1737 instruction->end = end;1737 instruction->end = end;
1738 instruction->is_const = is_const;
1739 instruction->safety_check_on = safety_check_on;1738 instruction->safety_check_on = safety_check_on;
17401739
1741 ir_ref_instruction(ptr, irb->current_basic_block);1740 ir_ref_instruction(ptr, irb->current_basic_block);
...@@ -1746,10 +1745,10 @@ static IrInstruction *ir_build_slice(IrBuilder *irb, Scope *scope, AstNode *sour...@@ -1746,10 +1745,10 @@ static IrInstruction *ir_build_slice(IrBuilder *irb, Scope *scope, AstNode *sour
1746}1745}
17471746
1748static IrInstruction *ir_build_slice_from(IrBuilder *irb, IrInstruction *old_instruction,1747static IrInstruction *ir_build_slice_from(IrBuilder *irb, IrInstruction *old_instruction,
1749 IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool is_const, bool safety_check_on)1748 IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on)
1750{1749{
1751 IrInstruction *new_instruction = ir_build_slice(irb, old_instruction->scope,1750 IrInstruction *new_instruction = ir_build_slice(irb, old_instruction->scope,
1752 old_instruction->source_node, ptr, start, end, is_const, safety_check_on);1751 old_instruction->source_node, ptr, start, end, safety_check_on);
1753 ir_link_new_instruction(new_instruction, old_instruction);1752 ir_link_new_instruction(new_instruction, old_instruction);
1754 return new_instruction;1753 return new_instruction;
1755}1754}
...@@ -5439,7 +5438,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -5439,7 +5438,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
5439 end_value = nullptr;5438 end_value = nullptr;
5440 }5439 }
54415440
5442 return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, slice_expr->is_const, true);5441 return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true);
5443}5442}
54445443
5445static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) {5444static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
...@@ -5903,6 +5902,11 @@ static bool is_slice(TypeTableEntry *type) {...@@ -5903,6 +5902,11 @@ static bool is_slice(TypeTableEntry *type) {
5903 return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;5902 return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;
5904}5903}
59055904
5905static bool slice_is_const(TypeTableEntry *type) {
5906 assert(is_slice(type));
5907 return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
5908}
5909
5906enum ImplicitCastMatchResult {5910enum ImplicitCastMatchResult {
5907 ImplicitCastMatchResultNo,5911 ImplicitCastMatchResultNo,
5908 ImplicitCastMatchResultYes,5912 ImplicitCastMatchResultYes,
...@@ -6778,7 +6782,7 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s...@@ -6778,7 +6782,7 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
6778 IrInstruction *array_ptr = ir_get_ref(ira, source_instr, array, true, false);6782 IrInstruction *array_ptr = ir_get_ref(ira, source_instr, array, true, false);
67796783
6780 IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope,6784 IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope,
6781 source_instr->source_node, array_ptr, start, end, false, false);6785 source_instr->source_node, array_ptr, start, end, false);
6782 TypeTableEntry *child_type = array_type->data.array.child_type;6786 TypeTableEntry *child_type = array_type->data.array.child_type;
6783 result->value.type = get_slice_type(ira->codegen, child_type, true);6787 result->value.type = get_slice_type(ira->codegen, child_type, true);
6784 ir_add_alloca(ira, result, result->value.type);6788 ir_add_alloca(ira, result, result->value.type);
...@@ -12076,17 +12080,17 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio...@@ -12076,17 +12080,17 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
12076 TypeTableEntry *return_type;12080 TypeTableEntry *return_type;
1207712081
12078 if (array_type->id == TypeTableEntryIdArray) {12082 if (array_type->id == TypeTableEntryIdArray) {
12079 return_type = get_slice_type(ira->codegen, array_type->data.array.child_type, instruction->is_const);12083 return_type = get_slice_type(ira->codegen, array_type->data.array.child_type, ptr_type->data.pointer.is_const);
12080 } else if (array_type->id == TypeTableEntryIdPointer) {12084 } else if (array_type->id == TypeTableEntryIdPointer) {
12081 return_type = get_slice_type(ira->codegen, array_type->data.pointer.child_type, instruction->is_const);12085 return_type = get_slice_type(ira->codegen, array_type->data.pointer.child_type,
12086 array_type->data.pointer.is_const);
12082 if (!end) {12087 if (!end) {
12083 ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value"));12088 ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value"));
12084 return ira->codegen->builtin_types.entry_invalid;12089 return ira->codegen->builtin_types.entry_invalid;
12085 }12090 }
12086 } else if (is_slice(array_type)) {12091 } else if (is_slice(array_type)) {
12087 return_type = get_slice_type(ira->codegen,12092 TypeTableEntry *ptr_type = array_type->data.structure.fields[slice_ptr_index].type_entry;
12088 array_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,12093 return_type = get_slice_type(ira->codegen, ptr_type->data.pointer.child_type, ptr_type->data.pointer.is_const);
12089 instruction->is_const);
12090 } else {12094 } else {
12091 ir_add_error(ira, &instruction->base,12095 ir_add_error(ira, &instruction->base,
12092 buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name)));12096 buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name)));
...@@ -12186,7 +12190,8 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio...@@ -12186,7 +12190,8 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
1218612190
12187 if (array_val) {12191 if (array_val) {
12188 size_t index = abs_offset + start_scalar;12192 size_t index = abs_offset + start_scalar;
12189 init_const_ptr_array(ira->codegen, ptr_val, array_val, index, instruction->is_const);12193 bool is_const = slice_is_const(return_type);
12194 init_const_ptr_array(ira->codegen, ptr_val, array_val, index, is_const);
12190 if (array_type->id == TypeTableEntryIdArray) {12195 if (array_type->id == TypeTableEntryIdArray) {
12191 ptr_val->data.x_ptr.mut = ptr_ptr->value.data.x_ptr.mut;12196 ptr_val->data.x_ptr.mut = ptr_ptr->value.data.x_ptr.mut;
12192 }12197 }
...@@ -12197,7 +12202,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio...@@ -12197,7 +12202,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
12197 zig_unreachable();12202 zig_unreachable();
12198 case ConstPtrSpecialRef:12203 case ConstPtrSpecialRef:
12199 init_const_ptr_ref(ira->codegen, ptr_val,12204 init_const_ptr_ref(ira->codegen, ptr_val,
12200 parent_ptr->data.x_ptr.data.ref.pointee, instruction->is_const);12205 parent_ptr->data.x_ptr.data.ref.pointee, slice_is_const(return_type));
12201 break;12206 break;
12202 case ConstPtrSpecialBaseArray:12207 case ConstPtrSpecialBaseArray:
12203 zig_unreachable();12208 zig_unreachable();
...@@ -12216,7 +12221,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio...@@ -12216,7 +12221,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
12216 }12221 }
1221712222
12218 IrInstruction *new_instruction = ir_build_slice_from(&ira->new_irb, &instruction->base, ptr_ptr,12223 IrInstruction *new_instruction = ir_build_slice_from(&ira->new_irb, &instruction->base, ptr_ptr,
12219 casted_start, end, instruction->is_const, instruction->safety_check_on);12224 casted_start, end, instruction->safety_check_on);
12220 ir_add_alloca(ira, new_instruction, return_type);12225 ir_add_alloca(ira, new_instruction, return_type);
1222112226
12222 return return_type;12227 return return_type;
src/ir_print.cpp-2
...@@ -642,8 +642,6 @@ static void ir_print_slice(IrPrint *irp, IrInstructionSlice *instruction) {...@@ -642,8 +642,6 @@ static void ir_print_slice(IrPrint *irp, IrInstructionSlice *instruction) {
642 if (instruction->end)642 if (instruction->end)
643 ir_print_other_instruction(irp, instruction->end);643 ir_print_other_instruction(irp, instruction->end);
644 fprintf(irp->f, "]");644 fprintf(irp->f, "]");
645 if (instruction->is_const)
646 fprintf(irp->f, "const");
647}645}
648646
649static void ir_print_member_count(IrPrint *irp, IrInstructionMemberCount *instruction) {647static void ir_print_member_count(IrPrint *irp, IrInstructionMemberCount *instruction) {
src/parser.cpp+1-7
...@@ -986,7 +986,7 @@ static AstNode *ast_parse_inline_expr(ParseContext *pc, size_t *token_index, boo...@@ -986,7 +986,7 @@ static AstNode *ast_parse_inline_expr(ParseContext *pc, size_t *token_index, boo
986SuffixOpExpression = InlineExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)986SuffixOpExpression = InlineExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
987FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)987FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
988ArrayAccessExpression : token(LBracket) Expression token(RBracket)988ArrayAccessExpression : token(LBracket) Expression token(RBracket)
989SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) token(RBracket) option(token(Const))989SliceExpression = "[" Expression "..." option(Expression) "]"
990FieldAccessExpression : token(Dot) token(Symbol)990FieldAccessExpression : token(Dot) token(Symbol)
991StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression991StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression
992*/992*/
...@@ -1022,12 +1022,6 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index,...@@ -1022,12 +1022,6 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index,
10221022
1023 ast_eat_token(pc, token_index, TokenIdRBracket);1023 ast_eat_token(pc, token_index, TokenIdRBracket);
10241024
1025 Token *const_tok = &pc->tokens->at(*token_index);
1026 if (const_tok->id == TokenIdKeywordConst) {
1027 *token_index += 1;
1028 node->data.slice_expr.is_const = true;
1029 }
1030
1031 inline_expr = node;1025 inline_expr = node;
1032 } else if (ellipsis_or_r_bracket->id == TokenIdRBracket) {1026 } else if (ellipsis_or_r_bracket->id == TokenIdRBracket) {
1033 *token_index += 1;1027 *token_index += 1;
test/cases/cast.zig+22
...@@ -120,6 +120,11 @@ fn returnNullLitFromMaybeTypeErrorRef() -> %?&A {...@@ -120,6 +120,11 @@ fn returnNullLitFromMaybeTypeErrorRef() -> %?&A {
120120
121test "peer type resolution: ?T and T" {121test "peer type resolution: ?T and T" {
122 assert(??peerTypeTAndMaybeT(true, false) == 0);122 assert(??peerTypeTAndMaybeT(true, false) == 0);
123 assert(??peerTypeTAndMaybeT(false, false) == 3);
124 comptime {
125 assert(??peerTypeTAndMaybeT(true, false) == 0);
126 assert(??peerTypeTAndMaybeT(false, false) == 3);
127 }
123}128}
124fn peerTypeTAndMaybeT(c: bool, b: bool) -> ?usize {129fn peerTypeTAndMaybeT(c: bool, b: bool) -> ?usize {
125 if (c) {130 if (c) {
...@@ -128,3 +133,20 @@ fn peerTypeTAndMaybeT(c: bool, b: bool) -> ?usize {...@@ -128,3 +133,20 @@ fn peerTypeTAndMaybeT(c: bool, b: bool) -> ?usize {
128133
129 return usize(3);134 return usize(3);
130}135}
136
137
138test "peer type resolution: [0]u8 and []const u8" {
139 assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
140 assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
141 comptime {
142 assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
143 assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
144 }
145}
146fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) -> []const u8 {
147 if (a) {
148 return []const u8 {};
149 }
150
151 return slice[0...1];
152}
test/cases/const_slice_child.zig+1-1
...@@ -21,7 +21,7 @@ fn foo(args: [][]const u8) {...@@ -21,7 +21,7 @@ fn foo(args: [][]const u8) {
21}21}
2222
23fn bar(argc: usize) {23fn bar(argc: usize) {
24 const args = %%debug.global_allocator.alloc([]u8, argc);24 const args = %%debug.global_allocator.alloc([]const u8, argc);
25 for (args) |_, i| {25 for (args) |_, i| {
26 const ptr = argv[i];26 const ptr = argv[i];
27 args[i] = ptr[0...strlen(ptr)];27 args[i] = ptr[0...strlen(ptr)];