←back to thread

452 points birdculture | 8 comments | | HN request time: 0.824s | source | bottom
1. CobrastanJorji ◴[] No.43979684[source]
Regarding the first example, the longest() function, why couldn't the compiler figure it out itself? What is the design flaw?
replies(3): >>43979765 #>>43979986 #>>43980940 #
2. mplanchard ◴[] No.43979765[source]
You’re passing in two references and returning a reference.

The compiler knows the returned reference must be tied to one of the incoming references (since you cannot return a reference to something created within the function, and all inputs are references, the output must therefore be referencing the input). But the compiler can’t know which reference the result comes from unless you tell it.

Theoretically it could tell by introspecting the function body, but the compiler only works on signatures, so the annotation must be added to the function signature to let it determine the expected lifetime of the returned reference.

replies(1): >>43980841 #
3. raincole ◴[] No.43979986[source]
It's a design choice.

To make a compiler automatically handle all of the cases like that, you will need to do an extensive static analysis, which would make compiling take forever.

replies(1): >>43980933 #
4. NobodyNada ◴[] No.43980841[source]
> Theoretically it could tell by introspecting the function body, but the compiler only works on signatures

Note that this is an intentional choice rather than a limitation, because if the compiler analyzed the function body to determine lifetimes of parameters and return values, then changing the body of a function could be a non-obvious breaking API change. If lifetimes are only dependent on the signature, then its explicit what promises you are or are not making to callers of a function about object lifetimes, and changing those promises must be done intentionally by changing the signature rather than implicitly.

replies(2): >>43980952 #>>43983527 #
5. j16sdiz ◴[] No.43980933[source]
Would be nice if an IDE can autofix it.

Maybe autofix as we type, or autofix when it save the document / advance to next line.

6. ordu ◴[] No.43980940[source]
Compiler can figure that out, but the thing is compiler needs also to understand lifetimes at the site where this function is called. In general case compiler will not look into the code of a called function to see what it does, compiler relies on a function declaration.

That `longest` if defined without explicit lifetimes treated like a lifetime of a return value is the same as of the first argument. It is a rule "lifetime elision", which allows to not write lifetimes explicitly in most cases.

But `longest` can return a second reference also. With added lifetimes the header of the function says exactly that: the lifetime of a return value is a minimum of lifetimes of arguments. Not the lifetime of the first one.

7. j16sdiz ◴[] No.43980952{3}[source]
> changing the body of a function could be a non-obvious breaking API change

This. Many trival changes breaks API. This is not ideal for library developers.

You can argue it is broken already, but this is forcing the breakage onto every api caller, not just some broken caller.

8. mplanchard ◴[] No.43983527{3}[source]
Oh yes, I didn’t mean to make it sound like a problem. I personally strongly prefer signature-based typing vs like in Typescript where you can easily be returning an entirely unintentional type and not realize it until you try to use it in an explicitly typed context down the line.

I also imagine it’s much faster for the type-checking pass of the compiler to just look at the signatures.