| author | |
| committer | |
| log | bcd04089ebf563659972c1a0fe1864521b128d37 |
| tree | 7f64f0b59b209712229d74113674cb7572a77a9d |
| parent | b1aa2857ffc631041a36e26b606c060eec1aa6bb |
4 files changed, 26 insertions(+), 0 deletions(-)
src-self-hosted/astgen.zig+1| ... | ... | @@ -1235,6 +1235,7 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For) |
| 1235 | 1235 | break :blk index_ptr; |
| 1236 | 1236 | }; |
| 1237 | 1237 | const array_ptr = try expr(mod, &for_scope.base, .ref, for_node.array_expr); |
| 1238 | _ = try addZIRUnOp(mod, &for_scope.base, for_node.array_expr.firstToken(), .ensure_indexable, array_ptr); | |
| 1238 | 1239 | const cond_src = tree.token_locs[for_node.array_expr.firstToken()].start; |
| 1239 | 1240 | const len_ptr = try addZIRInst(mod, &for_scope.base, cond_src, zir.Inst.FieldPtr, .{ |
| 1240 | 1241 | .object_ptr = array_ptr, |
src-self-hosted/type.zig+7| ... | ... | @@ -2675,6 +2675,13 @@ pub const Type = extern union { |
| 2675 | 2675 | }; |
| 2676 | 2676 | } |
| 2677 | 2677 | |
| 2678 | pub fn isIndexable(self: Type) bool { | |
| 2679 | const zig_tag = self.zigTypeTag(); | |
| 2680 | // TODO tuples are indexable | |
| 2681 | return zig_tag == .Array or zig_tag == .Vector or self.isSlice() or | |
| 2682 | (self.isSinglePointer() and self.elemType().zigTypeTag() == .Array); | |
| 2683 | } | |
| 2684 | ||
| 2678 | 2685 | /// This enum does not directly correspond to `std.builtin.TypeId` because |
| 2679 | 2686 | /// it has extra enum tags in it, as a way of using less memory. For example, |
| 2680 | 2687 | /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types |
src-self-hosted/zir.zig+4| ... | ... | @@ -137,6 +137,8 @@ pub const Inst = struct { |
| 137 | 137 | ensure_result_used, |
| 138 | 138 | /// Emits a compile error if an error is ignored. |
| 139 | 139 | ensure_result_non_error, |
| 140 | /// Emits a compile error if operand cannot be indexed. | |
| 141 | ensure_indexable, | |
| 140 | 142 | /// Create a `E!T` type. |
| 141 | 143 | error_union_type, |
| 142 | 144 | /// Create an error set. |
| ... | ... | @@ -278,6 +280,7 @@ pub const Inst = struct { |
| 278 | 280 | .alloc, |
| 279 | 281 | .ensure_result_used, |
| 280 | 282 | .ensure_result_non_error, |
| 283 | .ensure_indexable, | |
| 281 | 284 | .bitcast_result_ptr, |
| 282 | 285 | .ref, |
| 283 | 286 | .bitcast_ref, |
| ... | ... | @@ -409,6 +412,7 @@ pub const Inst = struct { |
| 409 | 412 | .elemptr, |
| 410 | 413 | .ensure_result_used, |
| 411 | 414 | .ensure_result_non_error, |
| 415 | .ensure_indexable, | |
| 412 | 416 | .@"export", |
| 413 | 417 | .floatcast, |
| 414 | 418 | .fieldptr, |
src-self-hosted/zir_sema.zig+14| ... | ... | @@ -48,6 +48,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! |
| 48 | 48 | .declval_in_module => return analyzeInstDeclValInModule(mod, scope, old_inst.castTag(.declval_in_module).?), |
| 49 | 49 | .ensure_result_used => return analyzeInstEnsureResultUsed(mod, scope, old_inst.castTag(.ensure_result_used).?), |
| 50 | 50 | .ensure_result_non_error => return analyzeInstEnsureResultNonError(mod, scope, old_inst.castTag(.ensure_result_non_error).?), |
| 51 | .ensure_indexable => return analyzeInstEnsureIndexable(mod, scope, old_inst.castTag(.ensure_indexable).?), | |
| 51 | 52 | .ref => return analyzeInstRef(mod, scope, old_inst.castTag(.ref).?), |
| 52 | 53 | .ret_ptr => return analyzeInstRetPtr(mod, scope, old_inst.castTag(.ret_ptr).?), |
| 53 | 54 | .ret_type => return analyzeInstRetType(mod, scope, old_inst.castTag(.ret_type).?), |
| ... | ... | @@ -382,6 +383,19 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst. |
| 382 | 383 | } |
| 383 | 384 | } |
| 384 | 385 | |
| 386 | fn analyzeInstEnsureIndexable(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | |
| 387 | const operand = try resolveInst(mod, scope, inst.positionals.operand); | |
| 388 | const elem_ty = operand.ty.elemType(); | |
| 389 | if (elem_ty.isIndexable()) { | |
| 390 | return mod.constVoid(scope, operand.src); | |
| 391 | } else { | |
| 392 | // TODO error notes | |
| 393 | // error: type '{}' does not support indexing | |
| 394 | // note: for loop operand must be an array, a slice or a tuple | |
| 395 | return mod.fail(scope, operand.src, "for loop operand must be an array, a slice or a tuple", .{}); | |
| 396 | } | |
| 397 | } | |
| 398 | ||
| 385 | 399 | fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { |
| 386 | 400 | const var_type = try resolveType(mod, scope, inst.positionals.operand); |
| 387 | 401 | // TODO this should happen only for var allocs |