Reputation: 46598
The value returned from T::bar
has the 'static
lifetime, so Test2::foo
scope doesn't need to own anything. Returning &[T::bar()]
as &'static [&'static StructType]
should be safe? Test:foo
compiles without issue so I was expecting Test2::foo
to compile as well.
Code
pub struct StructType {
a: &'static str,
}
pub trait Foo {
fn foo() -> &'static [&'static StructType];
fn bar() -> &'static StructType;
}
pub struct Test;
impl Foo for Test {
fn foo() -> &'static [&'static StructType] {
&[&StructType { a: "asdf" }]
}
fn bar() -> &'static StructType {
&StructType { a: "asdf" }
}
}
pub struct Test2<T: Foo>(T);
impl<T: Foo> Test2<T> {
pub fn foo() -> &'static [&'static StructType] {
&[T::bar()]
}
}
Error
error[E0515]: cannot return reference to temporary value
--> src/lib.rs:26:9
|
26 | &[T::bar()]
| ^----------
| ||
| |temporary value created here
| returns a reference to data owned by the current function
Upvotes: 2
Views: 1332
Reputation: 430711
The RFC that added the automatic promotion of references to values to 'static
states:
Promote constexpr rvalues to values in static memory instead of stack slots, and expose those in the language by being able to directly create 'static references to them.
Literal values are the most obvious constant expressions. However, a function call is not constant unless explicitly marked as such using const
. However, as of Rust 1.31, the types of operations that are available in a user-defined const
function are fairly limited. Literal values are allowed:
const fn bar() -> &'static StructType {
&StructType("asdf")
}
const fn combo() -> &'static [&'static StructType; 1] {
&[Self::bar()]
}
Converting from a reference to an array to a slice is not allowed in a const
function yet, so that needs to be in a different function:
fn wombo() -> &'static [&'static StructType] {
Self::combo()
}
Additionally, you cannot define const
functions in a trait.
See also:
What I really need are 1) have
T::bar()
return a constant, 2) haveTest:foo
return an array constant, that is constructed fromT::bar()
andU::bar()
andU
,T
are generic parameter toTest
You cannot do this
fn example<T>() {
static NO_CAN_DO: T = unimplemented!();
}
error[E0401]: can't use type parameters from outer function
--> src/lib.rs:2:23
|
1 | fn example<T>() {
| ------- - type variable from outer function
| |
| try adding a local type parameter in this method instead
2 | static NO_CAN_DO: T = unimplemented!();
| ^ use of type variable from outer function
See also:
Upvotes: 2
Reputation: 1324
I think you're thinking about lifetimes the wrong way. It seems like you use them to "declare" how long you want it to live, but you can't change the lifetime of a reference. All the lifetime specifiers do is to help the compiler to understand the lifetime in cases where it doesn't have the information to elide it.
Chapter 15.4.7 Static from Rust by Example should help you out.
Basically, there are only two ways you can create 'static
data:
static
declaration.&'static str
.You could achieve the same as above by declaring lifetimes specifiers like you normally do in Rust (but the compiler suggested a 'static
lifetime since you hadn't declared any lifetimes yourself). See below.
The main point is that, with the exception of &'static str
, a lifetime can never be changed by annotating lifetimes in your functions. When you write &[T::bar()]
, the array is not a constant and will get dropped when you leave the scope if your function. If you want it to live with a 'static
lifetime, you need to make it a constant like I show below.
Now that's probably not exactly what you wanted to do but it will compile and I hope explain the difference:
const ARR: &'static [&'static StructType] = &[&StructType { a: "asdf" }];
pub struct StructType {
a: &'static str,
}
pub trait Foo<'a> {
fn foo() -> &'a [&'a StructType];
fn bar() -> &'a StructType;
}
pub struct Test;
impl<'a> Foo<'a> for Test {
fn foo() -> &'a [&'a StructType] {
&[&StructType { a: "asdf" }]
}
fn bar() -> &'a StructType {
&StructType { a: "asdf" }
}
}
pub struct Test2<T: Foo<'static>>(T);
impl<T: Foo<'static>> Test2<T> {
pub fn foo() -> &'static [&'static StructType] {
ARR
}
}
Upvotes: 0