You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Instead of guaranteeing that a copy happens when returning by value, could we give a weaker guarantee that there is no lifetime issue, but that we may or may not make a copy?
What I'm thinking is: we could say that a function that returns by value may return a reference to anything that it knows lives at least as long as any of its parameters (including me). Then at the call site, we can check whether the returned value outlives any of the function parameters and make a copy if so. Then:
// F doesn't make a copy; returned value lives at least as long as parameter s
fn F(s: String) -> String { return s; }
// G makes a copy: v doesn't live long enough
fn G(s: String) -> String {
let v: String = "foo" + s + "bar";
return v;
}
fn Print(s: String);
fn H() {
// Parameter of `F` can be kept alive until `;`, so we know
// the return value lives at least that long and don't need
// to make any copies.
Print(F("hello"));
// `x` outlives the function argument, so we make a copy here.
let x: String = F("hello");
Print(x);
}
I suppose we can avoid making a copy even in the second case in H by lifetime-extending the "hello" temporary. I'm not sure that's a good idea; it might be too unpredictable.
One problem with this is that the function return is creating an immutable view, and we need the callee to know how long it's promising that returned value will remain immutable for. I suppose this is nothing new; this is analogous to a classic C++ issue:
const string &s = v[i];
v.push_back("x");
use(s);
... where this either works or fails depending on whether v[i] produces a reference to an existing object (eg, v is vector<string>) or ends up binding s to a temporary (eg, v is vector<const char*>). We might want some simple syntax to force a copy and end a chain of immutable views. (You could use var for that, but that also implies mutability, which might be undesirable.)
There's also a calling convention complexity issue with this kind of approach: if F can either return a handle to some existing object or copy to some caller-provided storage, then the caller always needs to provide the storage and may need to perform a branch to tell whether it should provide a copy. That seems like something we could handle but I'm not sure whether it'll be worthwhile unless we get to avoid a lot of copies.
Instead of guaranteeing that a copy happens when returning by value, could we give a weaker guarantee that there is no lifetime issue, but that we may or may not make a copy?
What I'm thinking is: we could say that a function that returns by value may return a reference to anything that it knows lives at least as long as any of its parameters (including
me
). Then at the call site, we can check whether the returned value outlives any of the function parameters and make a copy if so. Then:I suppose we can avoid making a copy even in the second case in
H
by lifetime-extending the"hello"
temporary. I'm not sure that's a good idea; it might be too unpredictable.One problem with this is that the function return is creating an immutable view, and we need the callee to know how long it's promising that returned value will remain immutable for. I suppose this is nothing new; this is analogous to a classic C++ issue:
... where this either works or fails depending on whether
v[i]
produces a reference to an existing object (eg,v
isvector<string>
) or ends up bindings
to a temporary (eg,v
isvector<const char*>
). We might want some simple syntax to force a copy and end a chain of immutable views. (You could usevar
for that, but that also implies mutability, which might be undesirable.)There's also a calling convention complexity issue with this kind of approach: if
F
can either return a handle to some existing object or copy to some caller-provided storage, then the caller always needs to provide the storage and may need to perform a branch to tell whether it should provide a copy. That seems like something we could handle but I'm not sure whether it'll be worthwhile unless we get to avoid a lot of copies.Originally posted by @zygoloid in #821 (comment)
The text was updated successfully, but these errors were encountered: