#function called at runtime cannot return value at comptime
1 messages · Page 1 of 1 (latest)
im assuming you are trying to get a function pointer if so return Self{ .fe = &baseOne };
if not would need to see more code
baseOne is a [4]u64
can you show the code?
Technically "can't" which is annoying... let me see if I can figure out somewhat to extract the gist of it.
Could somehow the Self = @This() have some indirect non-determinism? Like something on the type maybe
This was actually working yesterday, and I don't see any change in my git repo...
I don't believe in ghosts, but AFAIK my zig version hasn't changed.
I'm a bit surprised at the line the error is pointing at... is basically creating a type value with a field which is a [4]u64 🤷
(definitely not a pointer, which would be wrong for comptime)
does the function do anything like print to stderr/stdout or any other such I/O
nop
let me try something if triggers the same error and is sharable
@slow panther , @lapis moss ,
pub fn oneTest() Self {
return comptime {
var baseOneTest: [4]u64 = undefined;
baseOneTest[0] = 0x1fffffffe;
baseOneTest[1] = 0x5884b7fa00034802;
baseOneTest[2] = 0x998c4fefecbc4ff5;
baseOneTest[3] = 0x1824b159acc5056f;
return Self{ .fe = baseOneTest };
};
}
Error:
error: function called at runtime cannot return value at comptime
return Self{ .fe = baseOneTest };
there only way i can even get that error is by doing exactly what it says, returning at comptime in a runtime call
fn f() u8 {
comptime return 1;
}
at the call site comptime oneTest();
function calls are at runtime unless already in a comptime scope
You mean that I should always do comptime oneTest() in each caller?
or something like this
pub fn oneTest() [4]u64 {
const baseOneTest: [4]u64 = comptime blk: {
var baseOneTest: [4]u64 = undefined;
baseOneTest[0] = 0x1fffffffe;
baseOneTest[1] = 0x5884b7fa00034802;
baseOneTest[2] = 0x998c4fefecbc4ff5;
baseOneTest[3] = 0x1824b159acc5056f;
break :blk baseOneTest;
};
return baseOneTest;
}
basically dont return inside comptime scope, unless the function is only called at comptime
Interesting... feels I've a mental gap about what it means to return inside a comptime.
I'm actually not sure what that means now that I think about it
Compared with that break :blk ...
it only makes sense if the caller is comptime
Very interesting, let me try.
@lapis moss, looks like this fixed the error.
I'm a bit surprised how this could have worked and "suddenly" (which of course always have an explanation) stop working.
From what I imagine, in some new caller this methods might be used and wasn't comptime, and this fact of returning inside comptime become relevant? Sounds plausible?
might be something like this?
const outside_function = oneTest(); // FINE - outside of function so is comptime
fn func() void {
const inside_function = oneTest(); // ERROR - inside function which means runtime (unless `func` is called at comptime)
}
comptime return was added recently. It was considered that return should really be runtime only.
Not really sure I agree that was a good idea but... 😄
I think this was you @humble tree, right?
comptime return is now invalid in a function called at runtime
That's because it's trying to do runtime control flow at comptime, which is not possible
It didn't used to work, it was just silently equivalent to return comptime (which is what you probably want) due to #7056
Yeah, just skimmed the thread, that's exactly what you're running into
So @stuck otter your confusion probably comes from the fact that this changed literally yesterday
(And comptime return == comptime { return; })
comptime blocks and expressions used to be a bit broken: they didn't actually force their contents to be completely comptime-evaluated, only certain things like function calls. That's the only reason comptime return was ever valid (in a function called at runtime)
This makes me wonder if my zig version is being updated automatically by zls vscode extension or something?
no, the extension only updates zls
Ah ok, I think I understand what happened.
I also tried some old git commit which definitely was working some weeks ago, but at that time I was using a different zig compiler.
cool
Very tricky to test old code when you're changing your compiler often heh
So why I would ever want to use comptime { ... return ..; } ?
In my experience Zig's breaking changes don't tend to be too painful to work around
You wouldn't
I like that.
I mean, I like that I shouldn't
It's a bit confusing having that option, so good that isn't allowed/recommended.
All comptime syntax does is ensures some expression is evaluated at comptime. It can't fundamentally change control flow or anything like that
So this pattern will most probably mean that the function call will be inlined, right?
Is basically a funciont returning a constant
yea which means just a constant is better than a function call at all
Yeah, that'd be the idea. Note that you can shorten that:
return comptime blk: {
...
break :blk whatever;
};
oh that looks better
That's what I changed it to wherever the compiler or std was using the old thing
break without a label breaks to the enclosing loop, not to a block
But there's no ambiguity there
Breaking to a loop always requires a label
if you don't need to take an argument don't even bother with the function:
const baseOneTest: [4]u64 = blk: {
var temp: [4]u64 = undefined;
temp[0] = 0x1fffffffe;
temp[1] = 0x5884b7fa00034802;
temp[2] = 0x998c4fefecbc4ff5;
temp[3] = 0x1824b159acc5056f;
break :blk temp;
};
fn func() void {
var thing = baseOneTest;
}
while (true) {
break;
}
if break exited blocks, this would actually loop forever, cuz the break just exits the block but you're still in the loop
But even if that weren't the case, it's also just a clarity thing
If you see an unlabelled block, you know it doesn't give a result without having to read it all
Is this equivalent to:
const x = comptime blk: {
...
break :blk result;
};
return x;
Yes
@humble tree , the blk: label... which kind of semantic should have for its name?
That's kind of the "annoying" part for me.
You can use the name of the target as the label name
yeah but sounds redundant
The name blk is honestly fine in cases like this, but you could also go with result, or a more contextually appropriate name describing what the thing you're returning is
const foobar = foobar: {
break :foobar 5;
};
cool, like naming the returned value
so the name of the receiving variable can be contextual to the function, and the "break" label maybe more related to the value meaning inside the block
kind of naming a return parameter
ok, interesting, maybe i'm convinced :P
Pretty much yeah
I tend to do blk: { most of the time, but I may [start using] the target idea more honestly. It's nice if there's a lot going on, or the block is more than a page, or whatever.
From my side we can consider this thread solved, thanks everyone.
(Not sure if I can mark this solved or there's an "exit-flow")
done!