Lifetime error on struct referring to a parametrized function
If I write the code below, I get error[E0309]: the parameter type 'T' may not live long enough
.
struct Function<T> {
f: fn() -> T,
}
struct FunctionRef<'f, T> {
f: &'f Function<T>,
}
This fixes the error:
struct FunctionRef<'f, T: 'f> {
f: &'f Function<T>,
}
However, as far as I can tell, T
is not bound on the lifetime 'f
. Indeed, T
is a new object created when the function of type fn () -> T
is run.
Where am I missing something?
rust
add a comment |
If I write the code below, I get error[E0309]: the parameter type 'T' may not live long enough
.
struct Function<T> {
f: fn() -> T,
}
struct FunctionRef<'f, T> {
f: &'f Function<T>,
}
This fixes the error:
struct FunctionRef<'f, T: 'f> {
f: &'f Function<T>,
}
However, as far as I can tell, T
is not bound on the lifetime 'f
. Indeed, T
is a new object created when the function of type fn () -> T
is run.
Where am I missing something?
rust
This is effectively the same question as The compiler suggests I add a 'static lifetime because the parameter type may not live long enough, but I don't think that's what I want:T: 'f
does not mean that everyT
lives for at least'f
, it means thatT
cannot contain any references with a lifetime less than'f
.
– trentcl
Nov 20 '18 at 12:49
1
The only lifetime bound that makes sense here is usingT: 'static
. Since the function pointed to byf
does not take any arguments, it can't really return a reference with any other lifetime than the static lifetime. (The situation would be different if you changed the type off
to a generic typeF: Fn() -> T
, since this would also allow for closures, which can return captured references that have different lifetimes.)
– Sven Marnach
Nov 21 '18 at 9:28
add a comment |
If I write the code below, I get error[E0309]: the parameter type 'T' may not live long enough
.
struct Function<T> {
f: fn() -> T,
}
struct FunctionRef<'f, T> {
f: &'f Function<T>,
}
This fixes the error:
struct FunctionRef<'f, T: 'f> {
f: &'f Function<T>,
}
However, as far as I can tell, T
is not bound on the lifetime 'f
. Indeed, T
is a new object created when the function of type fn () -> T
is run.
Where am I missing something?
rust
If I write the code below, I get error[E0309]: the parameter type 'T' may not live long enough
.
struct Function<T> {
f: fn() -> T,
}
struct FunctionRef<'f, T> {
f: &'f Function<T>,
}
This fixes the error:
struct FunctionRef<'f, T: 'f> {
f: &'f Function<T>,
}
However, as far as I can tell, T
is not bound on the lifetime 'f
. Indeed, T
is a new object created when the function of type fn () -> T
is run.
Where am I missing something?
rust
rust
edited Nov 20 '18 at 7:16
hellow
5,11642142
5,11642142
asked Nov 20 '18 at 5:25
OlivierOlivier
38037
38037
This is effectively the same question as The compiler suggests I add a 'static lifetime because the parameter type may not live long enough, but I don't think that's what I want:T: 'f
does not mean that everyT
lives for at least'f
, it means thatT
cannot contain any references with a lifetime less than'f
.
– trentcl
Nov 20 '18 at 12:49
1
The only lifetime bound that makes sense here is usingT: 'static
. Since the function pointed to byf
does not take any arguments, it can't really return a reference with any other lifetime than the static lifetime. (The situation would be different if you changed the type off
to a generic typeF: Fn() -> T
, since this would also allow for closures, which can return captured references that have different lifetimes.)
– Sven Marnach
Nov 21 '18 at 9:28
add a comment |
This is effectively the same question as The compiler suggests I add a 'static lifetime because the parameter type may not live long enough, but I don't think that's what I want:T: 'f
does not mean that everyT
lives for at least'f
, it means thatT
cannot contain any references with a lifetime less than'f
.
– trentcl
Nov 20 '18 at 12:49
1
The only lifetime bound that makes sense here is usingT: 'static
. Since the function pointed to byf
does not take any arguments, it can't really return a reference with any other lifetime than the static lifetime. (The situation would be different if you changed the type off
to a generic typeF: Fn() -> T
, since this would also allow for closures, which can return captured references that have different lifetimes.)
– Sven Marnach
Nov 21 '18 at 9:28
This is effectively the same question as The compiler suggests I add a 'static lifetime because the parameter type may not live long enough, but I don't think that's what I want:
T: 'f
does not mean that every T
lives for at least 'f
, it means that T
cannot contain any references with a lifetime less than 'f
.– trentcl
Nov 20 '18 at 12:49
This is effectively the same question as The compiler suggests I add a 'static lifetime because the parameter type may not live long enough, but I don't think that's what I want:
T: 'f
does not mean that every T
lives for at least 'f
, it means that T
cannot contain any references with a lifetime less than 'f
.– trentcl
Nov 20 '18 at 12:49
1
1
The only lifetime bound that makes sense here is using
T: 'static
. Since the function pointed to by f
does not take any arguments, it can't really return a reference with any other lifetime than the static lifetime. (The situation would be different if you changed the type of f
to a generic type F: Fn() -> T
, since this would also allow for closures, which can return captured references that have different lifetimes.)– Sven Marnach
Nov 21 '18 at 9:28
The only lifetime bound that makes sense here is using
T: 'static
. Since the function pointed to by f
does not take any arguments, it can't really return a reference with any other lifetime than the static lifetime. (The situation would be different if you changed the type of f
to a generic type F: Fn() -> T
, since this would also allow for closures, which can return captured references that have different lifetimes.)– Sven Marnach
Nov 21 '18 at 9:28
add a comment |
1 Answer
1
active
oldest
votes
Short answer: You need T: 'f
because T
may contains field that hold references and fn() -> T
is covariant over T
.
To simplify things may help to understand ...
For a moment substitute fn() -> T
with T
, because for me it is more simple to explain what it is happening with lifetimes.
See the Note below why with this substitution does not change the lifetime related error.
struct Function<T> {
f: T,
}
struct FunctionRef<'f, T> {
f: &'f Function<T>,
}
This lead to the same error[E0309]: the parameter type 'T' may not live long enough
error.
FunctionRef
instances cannot outlive the reference it holds in f
field:
you declare a generic lifetime parameter 'f
inside angle brackets and then you use 'f
as an annotation
inside the struct body. See also the book.
But FunctionRef::f
depends on a type parameter T
. The explicit constraint T: 'f
guarantee that T
instances
does not outlive references holded by T
and FunctionRef
does not outlive FunctionRef::f
.
If it can help to understand substitute the generic T
with a specific Foo
type:
struct Foo<'a> {
n: &'a i32,
}
struct FunctionRef<'f, 'a: 'f> {
f: &'f Foo<'a>,
}
You need to constraint lifetime 'a
to be valid at least as long as 'f
lifetime, otherwise memory safety rules would be violated.
Note
I have considered the case f: T
equivalent of f: fn() -> T
because such type constructor is covariant over T
.
To grasp the meaning of fn() -> T
is covariant over T
, consider this struct:
struct Foo<'a> {
v: &'a i32
}
In this case is safe to assign to v
a value with a lifetime "bigger" than 'a
, for example:
let ref_value: &'static i32 = &100;
let foo = Foo { v: ref_value};
Now the same holds for the following struct:
struct Function<'a> {
f: fn() -> &'a i32
}
The field f
expects a function that returns a &i32
that outlive 'a
.
In this case it is safe to pass a function that returns a &i32
with a "bigger" lifetime, for example:
fn my_f() -> &'static i32 {
&100
}
fn main() {
let foo = Function { f: my_f};
}
There is quite a lot of type theory behind this, see the nomicom for a detailed explanation.
Thank you. I understand your statement and I agree with it. However it does not answer my question. In the case you are showing I agree thatT
should be live longer than the lifetime'f
. However, I still do not understand why the statement "T
should be live longer than the lifetime`'f" is true for the case I presented in my question. You say "This error has nothing to do with the fact that Function::f is a function". To this I want to ask "Why?". Sorry if I am dumb.
– Olivier
Nov 20 '18 at 9:54
I see your doubt, I've added a note.
– attdona
Nov 20 '18 at 10:17
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53386717%2flifetime-error-on-struct-referring-to-a-parametrized-function%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Short answer: You need T: 'f
because T
may contains field that hold references and fn() -> T
is covariant over T
.
To simplify things may help to understand ...
For a moment substitute fn() -> T
with T
, because for me it is more simple to explain what it is happening with lifetimes.
See the Note below why with this substitution does not change the lifetime related error.
struct Function<T> {
f: T,
}
struct FunctionRef<'f, T> {
f: &'f Function<T>,
}
This lead to the same error[E0309]: the parameter type 'T' may not live long enough
error.
FunctionRef
instances cannot outlive the reference it holds in f
field:
you declare a generic lifetime parameter 'f
inside angle brackets and then you use 'f
as an annotation
inside the struct body. See also the book.
But FunctionRef::f
depends on a type parameter T
. The explicit constraint T: 'f
guarantee that T
instances
does not outlive references holded by T
and FunctionRef
does not outlive FunctionRef::f
.
If it can help to understand substitute the generic T
with a specific Foo
type:
struct Foo<'a> {
n: &'a i32,
}
struct FunctionRef<'f, 'a: 'f> {
f: &'f Foo<'a>,
}
You need to constraint lifetime 'a
to be valid at least as long as 'f
lifetime, otherwise memory safety rules would be violated.
Note
I have considered the case f: T
equivalent of f: fn() -> T
because such type constructor is covariant over T
.
To grasp the meaning of fn() -> T
is covariant over T
, consider this struct:
struct Foo<'a> {
v: &'a i32
}
In this case is safe to assign to v
a value with a lifetime "bigger" than 'a
, for example:
let ref_value: &'static i32 = &100;
let foo = Foo { v: ref_value};
Now the same holds for the following struct:
struct Function<'a> {
f: fn() -> &'a i32
}
The field f
expects a function that returns a &i32
that outlive 'a
.
In this case it is safe to pass a function that returns a &i32
with a "bigger" lifetime, for example:
fn my_f() -> &'static i32 {
&100
}
fn main() {
let foo = Function { f: my_f};
}
There is quite a lot of type theory behind this, see the nomicom for a detailed explanation.
Thank you. I understand your statement and I agree with it. However it does not answer my question. In the case you are showing I agree thatT
should be live longer than the lifetime'f
. However, I still do not understand why the statement "T
should be live longer than the lifetime`'f" is true for the case I presented in my question. You say "This error has nothing to do with the fact that Function::f is a function". To this I want to ask "Why?". Sorry if I am dumb.
– Olivier
Nov 20 '18 at 9:54
I see your doubt, I've added a note.
– attdona
Nov 20 '18 at 10:17
add a comment |
Short answer: You need T: 'f
because T
may contains field that hold references and fn() -> T
is covariant over T
.
To simplify things may help to understand ...
For a moment substitute fn() -> T
with T
, because for me it is more simple to explain what it is happening with lifetimes.
See the Note below why with this substitution does not change the lifetime related error.
struct Function<T> {
f: T,
}
struct FunctionRef<'f, T> {
f: &'f Function<T>,
}
This lead to the same error[E0309]: the parameter type 'T' may not live long enough
error.
FunctionRef
instances cannot outlive the reference it holds in f
field:
you declare a generic lifetime parameter 'f
inside angle brackets and then you use 'f
as an annotation
inside the struct body. See also the book.
But FunctionRef::f
depends on a type parameter T
. The explicit constraint T: 'f
guarantee that T
instances
does not outlive references holded by T
and FunctionRef
does not outlive FunctionRef::f
.
If it can help to understand substitute the generic T
with a specific Foo
type:
struct Foo<'a> {
n: &'a i32,
}
struct FunctionRef<'f, 'a: 'f> {
f: &'f Foo<'a>,
}
You need to constraint lifetime 'a
to be valid at least as long as 'f
lifetime, otherwise memory safety rules would be violated.
Note
I have considered the case f: T
equivalent of f: fn() -> T
because such type constructor is covariant over T
.
To grasp the meaning of fn() -> T
is covariant over T
, consider this struct:
struct Foo<'a> {
v: &'a i32
}
In this case is safe to assign to v
a value with a lifetime "bigger" than 'a
, for example:
let ref_value: &'static i32 = &100;
let foo = Foo { v: ref_value};
Now the same holds for the following struct:
struct Function<'a> {
f: fn() -> &'a i32
}
The field f
expects a function that returns a &i32
that outlive 'a
.
In this case it is safe to pass a function that returns a &i32
with a "bigger" lifetime, for example:
fn my_f() -> &'static i32 {
&100
}
fn main() {
let foo = Function { f: my_f};
}
There is quite a lot of type theory behind this, see the nomicom for a detailed explanation.
Thank you. I understand your statement and I agree with it. However it does not answer my question. In the case you are showing I agree thatT
should be live longer than the lifetime'f
. However, I still do not understand why the statement "T
should be live longer than the lifetime`'f" is true for the case I presented in my question. You say "This error has nothing to do with the fact that Function::f is a function". To this I want to ask "Why?". Sorry if I am dumb.
– Olivier
Nov 20 '18 at 9:54
I see your doubt, I've added a note.
– attdona
Nov 20 '18 at 10:17
add a comment |
Short answer: You need T: 'f
because T
may contains field that hold references and fn() -> T
is covariant over T
.
To simplify things may help to understand ...
For a moment substitute fn() -> T
with T
, because for me it is more simple to explain what it is happening with lifetimes.
See the Note below why with this substitution does not change the lifetime related error.
struct Function<T> {
f: T,
}
struct FunctionRef<'f, T> {
f: &'f Function<T>,
}
This lead to the same error[E0309]: the parameter type 'T' may not live long enough
error.
FunctionRef
instances cannot outlive the reference it holds in f
field:
you declare a generic lifetime parameter 'f
inside angle brackets and then you use 'f
as an annotation
inside the struct body. See also the book.
But FunctionRef::f
depends on a type parameter T
. The explicit constraint T: 'f
guarantee that T
instances
does not outlive references holded by T
and FunctionRef
does not outlive FunctionRef::f
.
If it can help to understand substitute the generic T
with a specific Foo
type:
struct Foo<'a> {
n: &'a i32,
}
struct FunctionRef<'f, 'a: 'f> {
f: &'f Foo<'a>,
}
You need to constraint lifetime 'a
to be valid at least as long as 'f
lifetime, otherwise memory safety rules would be violated.
Note
I have considered the case f: T
equivalent of f: fn() -> T
because such type constructor is covariant over T
.
To grasp the meaning of fn() -> T
is covariant over T
, consider this struct:
struct Foo<'a> {
v: &'a i32
}
In this case is safe to assign to v
a value with a lifetime "bigger" than 'a
, for example:
let ref_value: &'static i32 = &100;
let foo = Foo { v: ref_value};
Now the same holds for the following struct:
struct Function<'a> {
f: fn() -> &'a i32
}
The field f
expects a function that returns a &i32
that outlive 'a
.
In this case it is safe to pass a function that returns a &i32
with a "bigger" lifetime, for example:
fn my_f() -> &'static i32 {
&100
}
fn main() {
let foo = Function { f: my_f};
}
There is quite a lot of type theory behind this, see the nomicom for a detailed explanation.
Short answer: You need T: 'f
because T
may contains field that hold references and fn() -> T
is covariant over T
.
To simplify things may help to understand ...
For a moment substitute fn() -> T
with T
, because for me it is more simple to explain what it is happening with lifetimes.
See the Note below why with this substitution does not change the lifetime related error.
struct Function<T> {
f: T,
}
struct FunctionRef<'f, T> {
f: &'f Function<T>,
}
This lead to the same error[E0309]: the parameter type 'T' may not live long enough
error.
FunctionRef
instances cannot outlive the reference it holds in f
field:
you declare a generic lifetime parameter 'f
inside angle brackets and then you use 'f
as an annotation
inside the struct body. See also the book.
But FunctionRef::f
depends on a type parameter T
. The explicit constraint T: 'f
guarantee that T
instances
does not outlive references holded by T
and FunctionRef
does not outlive FunctionRef::f
.
If it can help to understand substitute the generic T
with a specific Foo
type:
struct Foo<'a> {
n: &'a i32,
}
struct FunctionRef<'f, 'a: 'f> {
f: &'f Foo<'a>,
}
You need to constraint lifetime 'a
to be valid at least as long as 'f
lifetime, otherwise memory safety rules would be violated.
Note
I have considered the case f: T
equivalent of f: fn() -> T
because such type constructor is covariant over T
.
To grasp the meaning of fn() -> T
is covariant over T
, consider this struct:
struct Foo<'a> {
v: &'a i32
}
In this case is safe to assign to v
a value with a lifetime "bigger" than 'a
, for example:
let ref_value: &'static i32 = &100;
let foo = Foo { v: ref_value};
Now the same holds for the following struct:
struct Function<'a> {
f: fn() -> &'a i32
}
The field f
expects a function that returns a &i32
that outlive 'a
.
In this case it is safe to pass a function that returns a &i32
with a "bigger" lifetime, for example:
fn my_f() -> &'static i32 {
&100
}
fn main() {
let foo = Function { f: my_f};
}
There is quite a lot of type theory behind this, see the nomicom for a detailed explanation.
edited Nov 21 '18 at 6:55
answered Nov 20 '18 at 9:41
attdonaattdona
3,72721320
3,72721320
Thank you. I understand your statement and I agree with it. However it does not answer my question. In the case you are showing I agree thatT
should be live longer than the lifetime'f
. However, I still do not understand why the statement "T
should be live longer than the lifetime`'f" is true for the case I presented in my question. You say "This error has nothing to do with the fact that Function::f is a function". To this I want to ask "Why?". Sorry if I am dumb.
– Olivier
Nov 20 '18 at 9:54
I see your doubt, I've added a note.
– attdona
Nov 20 '18 at 10:17
add a comment |
Thank you. I understand your statement and I agree with it. However it does not answer my question. In the case you are showing I agree thatT
should be live longer than the lifetime'f
. However, I still do not understand why the statement "T
should be live longer than the lifetime`'f" is true for the case I presented in my question. You say "This error has nothing to do with the fact that Function::f is a function". To this I want to ask "Why?". Sorry if I am dumb.
– Olivier
Nov 20 '18 at 9:54
I see your doubt, I've added a note.
– attdona
Nov 20 '18 at 10:17
Thank you. I understand your statement and I agree with it. However it does not answer my question. In the case you are showing I agree that
T
should be live longer than the lifetime'f
. However, I still do not understand why the statement "T
should be live longer than the lifetime`'f" is true for the case I presented in my question. You say "This error has nothing to do with the fact that Function::f is a function". To this I want to ask "Why?". Sorry if I am dumb.– Olivier
Nov 20 '18 at 9:54
Thank you. I understand your statement and I agree with it. However it does not answer my question. In the case you are showing I agree that
T
should be live longer than the lifetime'f
. However, I still do not understand why the statement "T
should be live longer than the lifetime`'f" is true for the case I presented in my question. You say "This error has nothing to do with the fact that Function::f is a function". To this I want to ask "Why?". Sorry if I am dumb.– Olivier
Nov 20 '18 at 9:54
I see your doubt, I've added a note.
– attdona
Nov 20 '18 at 10:17
I see your doubt, I've added a note.
– attdona
Nov 20 '18 at 10:17
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53386717%2flifetime-error-on-struct-referring-to-a-parametrized-function%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
This is effectively the same question as The compiler suggests I add a 'static lifetime because the parameter type may not live long enough, but I don't think that's what I want:
T: 'f
does not mean that everyT
lives for at least'f
, it means thatT
cannot contain any references with a lifetime less than'f
.– trentcl
Nov 20 '18 at 12:49
1
The only lifetime bound that makes sense here is using
T: 'static
. Since the function pointed to byf
does not take any arguments, it can't really return a reference with any other lifetime than the static lifetime. (The situation would be different if you changed the type off
to a generic typeF: Fn() -> T
, since this would also allow for closures, which can return captured references that have different lifetimes.)– Sven Marnach
Nov 21 '18 at 9:28