From aafb0b90822e55135e1c50962768e54e6c62b164 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 22 Apr 2017 12:19:20 -0400 Subject: [PATCH] slicing now returns correct const-ness also remove the ability to override constness when slicing closes #334 --- doc/langref.md | 2 +- src/all_types.hpp | 2 -- src/ast_render.cpp | 2 -- src/ir.cpp | 33 ++++++++++++++++++-------------- src/ir_print.cpp | 2 -- src/parser.cpp | 8 +------- test/cases/cast.zig | 22 +++++++++++++++++++++ test/cases/const_slice_child.zig | 2 +- 8 files changed, 44 insertions(+), 29 deletions(-) diff --git a/doc/langref.md b/doc/langref.md index 25a99e36b6..54017c0735 100644 --- a/doc/langref.md +++ b/doc/langref.md @@ -133,7 +133,7 @@ FnCallExpression = "(" list(Expression, ",") ")" ArrayAccessExpression = "[" Expression "]" -SliceExpression = "[" Expression "..." option(Expression) "]" option("const") +SliceExpression = "[" Expression "..." option(Expression) "]" ContainerInitExpression = "{" ContainerInitBody "}" diff --git a/src/all_types.hpp b/src/all_types.hpp index 1d8c094c5d..e0f3e3961b 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -532,7 +532,6 @@ struct AstNodeSliceExpr { AstNode *array_ref_expr; AstNode *start; AstNode *end; - bool is_const; }; struct AstNodeFieldAccessExpr { @@ -2260,7 +2259,6 @@ struct IrInstructionSlice { IrInstruction *ptr; IrInstruction *start; IrInstruction *end; - bool is_const; bool safety_check_on; LLVMValueRef tmp_ptr; }; diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 36ce69387b..3e939c43e5 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -894,8 +894,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { if (node->data.slice_expr.end) render_node_grouped(ar, node->data.slice_expr.end); fprintf(ar->f, "]"); - if (node->data.slice_expr.is_const) - fprintf(ar->f, "const"); break; } case NodeTypeUnwrapErrorExpr: diff --git a/src/ir.cpp b/src/ir.cpp index 941210d583..00dc9229e6 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1729,13 +1729,12 @@ static IrInstruction *ir_build_memcpy_from(IrBuilder *irb, IrInstruction *old_in } static IrInstruction *ir_build_slice(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool is_const, bool safety_check_on) + IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on) { IrInstructionSlice *instruction = ir_build_instruction(irb, scope, source_node); instruction->ptr = ptr; instruction->start = start; instruction->end = end; - instruction->is_const = is_const; instruction->safety_check_on = safety_check_on; ir_ref_instruction(ptr, irb->current_basic_block); @@ -1746,10 +1745,10 @@ static IrInstruction *ir_build_slice(IrBuilder *irb, Scope *scope, AstNode *sour } static IrInstruction *ir_build_slice_from(IrBuilder *irb, IrInstruction *old_instruction, - IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool is_const, bool safety_check_on) + IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on) { IrInstruction *new_instruction = ir_build_slice(irb, old_instruction->scope, - old_instruction->source_node, ptr, start, end, is_const, safety_check_on); + old_instruction->source_node, ptr, start, end, safety_check_on); ir_link_new_instruction(new_instruction, old_instruction); return new_instruction; } @@ -5439,7 +5438,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node) end_value = nullptr; } - return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, slice_expr->is_const, true); + return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true); } static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) { @@ -5903,6 +5902,11 @@ static bool is_slice(TypeTableEntry *type) { return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice; } +static bool slice_is_const(TypeTableEntry *type) { + assert(is_slice(type)); + return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const; +} + enum ImplicitCastMatchResult { ImplicitCastMatchResultNo, ImplicitCastMatchResultYes, @@ -6778,7 +6782,7 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s IrInstruction *array_ptr = ir_get_ref(ira, source_instr, array, true, false); IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope, - source_instr->source_node, array_ptr, start, end, false, false); + source_instr->source_node, array_ptr, start, end, false); TypeTableEntry *child_type = array_type->data.array.child_type; result->value.type = get_slice_type(ira->codegen, child_type, true); ir_add_alloca(ira, result, result->value.type); @@ -12076,17 +12080,17 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio TypeTableEntry *return_type; if (array_type->id == TypeTableEntryIdArray) { - return_type = get_slice_type(ira->codegen, array_type->data.array.child_type, instruction->is_const); + return_type = get_slice_type(ira->codegen, array_type->data.array.child_type, ptr_type->data.pointer.is_const); } else if (array_type->id == TypeTableEntryIdPointer) { - return_type = get_slice_type(ira->codegen, array_type->data.pointer.child_type, instruction->is_const); + return_type = get_slice_type(ira->codegen, array_type->data.pointer.child_type, + array_type->data.pointer.is_const); if (!end) { ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value")); return ira->codegen->builtin_types.entry_invalid; } } else if (is_slice(array_type)) { - return_type = get_slice_type(ira->codegen, - array_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type, - instruction->is_const); + TypeTableEntry *ptr_type = array_type->data.structure.fields[slice_ptr_index].type_entry; + return_type = get_slice_type(ira->codegen, ptr_type->data.pointer.child_type, ptr_type->data.pointer.is_const); } else { ir_add_error(ira, &instruction->base, 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 if (array_val) { size_t index = abs_offset + start_scalar; - init_const_ptr_array(ira->codegen, ptr_val, array_val, index, instruction->is_const); + bool is_const = slice_is_const(return_type); + init_const_ptr_array(ira->codegen, ptr_val, array_val, index, is_const); if (array_type->id == TypeTableEntryIdArray) { ptr_val->data.x_ptr.mut = ptr_ptr->value.data.x_ptr.mut; } @@ -12197,7 +12202,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio zig_unreachable(); case ConstPtrSpecialRef: init_const_ptr_ref(ira->codegen, ptr_val, - parent_ptr->data.x_ptr.data.ref.pointee, instruction->is_const); + parent_ptr->data.x_ptr.data.ref.pointee, slice_is_const(return_type)); break; case ConstPtrSpecialBaseArray: zig_unreachable(); @@ -12216,7 +12221,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio } IrInstruction *new_instruction = ir_build_slice_from(&ira->new_irb, &instruction->base, ptr_ptr, - casted_start, end, instruction->is_const, instruction->safety_check_on); + casted_start, end, instruction->safety_check_on); ir_add_alloca(ira, new_instruction, return_type); return return_type; diff --git a/src/ir_print.cpp b/src/ir_print.cpp index fa8a9fe3b0..da00289e17 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -642,8 +642,6 @@ static void ir_print_slice(IrPrint *irp, IrInstructionSlice *instruction) { if (instruction->end) ir_print_other_instruction(irp, instruction->end); fprintf(irp->f, "]"); - if (instruction->is_const) - fprintf(irp->f, "const"); } static void ir_print_member_count(IrPrint *irp, IrInstructionMemberCount *instruction) { diff --git a/src/parser.cpp b/src/parser.cpp index 7cea800ac0..1da6a295fa 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -986,7 +986,7 @@ static AstNode *ast_parse_inline_expr(ParseContext *pc, size_t *token_index, boo SuffixOpExpression = InlineExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression) FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen) ArrayAccessExpression : token(LBracket) Expression token(RBracket) -SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) token(RBracket) option(token(Const)) +SliceExpression = "[" Expression "..." option(Expression) "]" FieldAccessExpression : token(Dot) token(Symbol) StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression */ @@ -1022,12 +1022,6 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index, ast_eat_token(pc, token_index, TokenIdRBracket); - Token *const_tok = &pc->tokens->at(*token_index); - if (const_tok->id == TokenIdKeywordConst) { - *token_index += 1; - node->data.slice_expr.is_const = true; - } - inline_expr = node; } else if (ellipsis_or_r_bracket->id == TokenIdRBracket) { *token_index += 1; diff --git a/test/cases/cast.zig b/test/cases/cast.zig index 74c2ab7b32..f6425ee464 100644 --- a/test/cases/cast.zig +++ b/test/cases/cast.zig @@ -120,6 +120,11 @@ fn returnNullLitFromMaybeTypeErrorRef() -> %?&A { test "peer type resolution: ?T and T" { assert(??peerTypeTAndMaybeT(true, false) == 0); + assert(??peerTypeTAndMaybeT(false, false) == 3); + comptime { + assert(??peerTypeTAndMaybeT(true, false) == 0); + assert(??peerTypeTAndMaybeT(false, false) == 3); + } } fn peerTypeTAndMaybeT(c: bool, b: bool) -> ?usize { if (c) { @@ -128,3 +133,20 @@ fn peerTypeTAndMaybeT(c: bool, b: bool) -> ?usize { return usize(3); } + + +test "peer type resolution: [0]u8 and []const u8" { + assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); + assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); + comptime { + assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); + assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); + } +} +fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) -> []const u8 { + if (a) { + return []const u8 {}; + } + + return slice[0...1]; +} diff --git a/test/cases/const_slice_child.zig b/test/cases/const_slice_child.zig index aa1531edac..9d7a32be81 100644 --- a/test/cases/const_slice_child.zig +++ b/test/cases/const_slice_child.zig @@ -21,7 +21,7 @@ fn foo(args: [][]const u8) { } fn bar(argc: usize) { - const args = %%debug.global_allocator.alloc([]u8, argc); + const args = %%debug.global_allocator.alloc([]const u8, argc); for (args) |_, i| { const ptr = argv[i]; args[i] = ptr[0...strlen(ptr)];