@TypeOf is single-handedly responsible for language specification complexity. For example the langref contains this text:
The expressions are evaluated, however they are guaranteed to have no runtime side-effects:
It's not too bad but it's certainly a special case. There is no other builtin or syntax that behaves this way.
This proposal is to remove the builtin entirely, along with introducing syntax that addresses the use cases for @TypeOf.
Additional motivation here is that anytype is awkward because it looks like a type but it's actually syntax. Renaming it to anyval (https://github.com/ziglang/zig/issues/5893) does not address that fundamental incongruity. However, unless @TypeOf is removed, then an additional way to get the inferred type is no good. Better to always rely on @TypeOf than to have two ways to do it.
Variable declaration example:
conststd=@import("std");constexpect=std.testing.expect;test"@TypeOf var decl"{constresult=foo();comptimeassert(@TypeOf(result)==i32);}fnfoo()i32{return1234;}
⬇️
conststd=@import("std");constexpect=std.testing.expect;test"var decl typeof syntax"{constresult:|T|=foo();comptimeassert(T==i32);}fnfoo()i32{return1234;}
Function parameter example:
conststd=@import("std");constexpect=std.testing.expect;test"@TypeOf function parameter"{tryexpect(foo(12)==12);}fnfoo(x:anytype)@TypeOf(x){returnx;}
⬇️
conststd=@import("std");constexpect=std.testing.expect;test"inferred function parameter type"{tryexpect(foo(12)==12);}fnfoo(x:|T|)T{returnx;}
Downside of this would be losing access to peer type resolution as a builtin. For example this function from std.math would need to be rewritten. Keep in mind that peer type resolution works on values, not types because comptime-known values influence the result.
pubfnclamp(val:anytype,lower:anytype,upper:anytype)@TypeOf(val,lower,upper){constT=@TypeOf(val,lower,upper);// ...}
⬇️
pubfnclamp(val:|V|,lower:|L|,upper:|U|)Clamp(.{val,lower,upper}){_=V;_=L;_=U;constT=Clamp(val,lower,upper);// ...}pubfnClamp(values:|V|)type{// implement peer type resolution in userland 🤮}
Plus if #32045 were accepted (which I am not intending to endorse by writing this), this function would be impossible to implement. However, if https://github.com/ziglang/zig/issues/3806 were accepted, then this function would be fairly reasonable to implement without @TypeOf.
`@TypeOf` is single-handedly responsible for language specification complexity. For example the langref contains this text:
> The expressions are evaluated, however they are guaranteed to have no *runtime* side-effects:
It's not too bad but it's certainly a special case. There is no other builtin or syntax that behaves this way.
This proposal is to remove the builtin entirely, along with introducing syntax that addresses the use cases for `@TypeOf`.
Additional motivation here is that `anytype` is awkward because it looks like a type but it's actually *syntax*. Renaming it to `anyval` (https://github.com/ziglang/zig/issues/5893) does not address that fundamental incongruity. However, unless `@TypeOf` is removed, then an additional way to get the inferred type is no good. Better to always rely on `@TypeOf` than to have two ways to do it.
Variable declaration example:
```zig
const std = @import("std");
const expect = std.testing.expect;
test "@TypeOf var decl" {
const result = foo();
comptime assert(@TypeOf(result) == i32);
}
fn foo() i32 {
return 1234;
}
```
⬇️
```zig
const std = @import("std");
const expect = std.testing.expect;
test "var decl typeof syntax" {
const result: |T| = foo();
comptime assert(T == i32);
}
fn foo() i32 {
return 1234;
}
```
Function parameter example:
```zig
const std = @import("std");
const expect = std.testing.expect;
test "@TypeOf function parameter" {
try expect(foo(12) == 12);
}
fn foo(x: anytype) @TypeOf(x) {
return x;
}
```
⬇️
```zig
const std = @import("std");
const expect = std.testing.expect;
test "inferred function parameter type" {
try expect(foo(12) == 12);
}
fn foo(x: |T|) T {
return x;
}
```
Downside of this would be losing access to peer type resolution as a builtin. For example this function from `std.math` would need to be rewritten. Keep in mind that peer type resolution works on *values, not types* because comptime-known values influence the result.
```zig
pub fn clamp(val: anytype, lower: anytype, upper: anytype) @TypeOf(val, lower, upper) {
const T = @TypeOf(val, lower, upper);
// ...
}
```
⬇️
```zig
pub fn clamp(val: |V|, lower: |L|, upper: |U|) Clamp(.{val, lower, upper}) {
_ = V;
_ = L;
_ = U;
const T = Clamp(val, lower, upper);
// ...
}
pub fn Clamp(values: |V|) type {
// implement peer type resolution in userland 🤮
}
```
Plus if #32045 were accepted (which I am not intending to endorse by writing this), this function would be impossible to implement. However, if https://github.com/ziglang/zig/issues/3806 were accepted, then this function would be fairly reasonable to implement without `@TypeOf`.