From 7611ed3484ad810fe10d3c303a04d66bfa0bd6fd Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 7 Apr 2017 17:56:01 -0400 Subject: [PATCH] allow implicit cast from `[N]T` to `&const []const T` closes #296 --- src/ir.cpp | 48 +++++++++++++++++++++++++++++++++++++++++---- std/build.zig | 28 +++++++++++++------------- test/cases/cast.zig | 5 +++++ 3 files changed, 63 insertions(+), 18 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) || diff --git a/std/build.zig b/std/build.zig index 8d54f01e1f..6f26112ce8 100644 --- a/std/build.zig +++ b/std/build.zig @@ -119,30 +119,30 @@ pub const Builder = struct { var zig_args = List([]const u8).init(self.allocator); defer zig_args.deinit(); - %return zig_args.append("build_exe"[0...]); // TODO issue #296 + %return zig_args.append("build_exe"); %return zig_args.append(exe.root_src); if (exe.verbose) { - %return zig_args.append("--verbose"[0...]); // TODO issue #296 + %return zig_args.append("--verbose"); } if (exe.release) { - %return zig_args.append("--release"[0...]); // TODO issue #296 + %return zig_args.append("--release"); } - %return zig_args.append("--name"[0...]); // TODO issue #296 + %return zig_args.append("--name"); %return zig_args.append(exe.name); switch (exe.target) { Target.Native => {}, Target.Cross => |cross_target| { - %return zig_args.append("--target-arch"[0...]); // TODO issue #296 + %return zig_args.append("--target-arch"); %return zig_args.append(targetArchName(cross_target.arch)); - %return zig_args.append("--target-os"[0...]); // TODO issue #296 + %return zig_args.append("--target-os"); %return zig_args.append(targetOsName(cross_target.os)); - %return zig_args.append("--target-environ"[0...]); // TODO issue #296 + %return zig_args.append("--target-environ"); %return zig_args.append(targetEnvironName(cross_target.environ)); }, } @@ -153,11 +153,11 @@ pub const Builder = struct { const tmp_file_name = "linker.ld.tmp"; // TODO issue #298 io.writeFile(tmp_file_name, script, self.allocator) %% |err| debug.panic("unable to write linker script: {}\n", @errorName(err)); - %return zig_args.append("--linker-script"[0...]); // TODO issue #296 - %return zig_args.append(tmp_file_name[0...]); // TODO issue #296 + %return zig_args.append("--linker-script"); + %return zig_args.append(tmp_file_name); }, LinkerScript.Path => |path| { - %return zig_args.append("--linker-script"[0...]); // TODO issue #296 + %return zig_args.append("--linker-script"); %return zig_args.append(path); }, } @@ -166,23 +166,23 @@ pub const Builder = struct { var it = exe.link_libs.iterator(); while (true) { const entry = it.next() ?? break; - %return zig_args.append("--library"[0...]); // TODO issue #296 + %return zig_args.append("--library"); %return zig_args.append(entry.key); } } for (self.include_paths.toSliceConst()) |include_path| { - %return zig_args.append("-isystem"[0...]); // TODO issue #296 + %return zig_args.append("-isystem"); %return zig_args.append(include_path); } for (self.rpaths.toSliceConst()) |rpath| { - %return zig_args.append("-rpath"[0...]); // TODO issue #296 + %return zig_args.append("-rpath"); %return zig_args.append(rpath); } for (self.lib_paths.toSliceConst()) |lib_path| { - %return zig_args.append("--library-path"[0...]); // TODO issue #296 + %return zig_args.append("--library-path"); %return zig_args.append(lib_path); } diff --git a/test/cases/cast.zig b/test/cases/cast.zig index 05d9243fe3..d0ea25452c 100644 --- a/test/cases/cast.zig +++ b/test/cases/cast.zig @@ -70,3 +70,8 @@ test "integer literal to &const int" { const x: &const i32 = 3; assert(*x == 3); } + +test "string literal to &const []const u8" { + const x: &const []const u8 = "hello"; + assert(mem.eql(u8, *x, "hello")); +}