rust - Trouble implementing higher ranked lifetime type bound for a byte slice -
i trying implement trait on &'a [u8]
, use in implementation uses higher ranked lifetimes, e.g.:
pub trait intotest<'a, t> { fn into_test(&'a self) -> t self: sized; } impl<'a> intotest<'a, &'a [u8]> &'a [u8] { fn into_test(&'a self) -> &'a [u8] { self } } fn higher_ranked_lifetime<t>(test: t) t: for<'a> intotest<'a, &'a [u8]> { let _t = test.into_test(); } fn main() { println!("hello, world!"); let vec = vec![1u8]; let slice = &vec[..]; higher_ranked_lifetime(slice); }
short url: http://is.gd/1qkhyk
the error getting is:
<anon>:19:5: 19:27 error: trait `for<'a> intotest<'a, &'a [u8]>` not implemented type `&[u8]` [e0277] <anon>:19 higher_ranked_lifetime(slice);
how should doing this? right thing do? not want scope higher_ranked_lifetime
specific lifetime, have applicable byte slice passed it.
this not correct way, , compiler right.
one way can see why @ type (the slice) , trait think implements side side:
for<'a> intotest<'a, &'a [u8]> &'a [u8]
here i've added lifetime parameter on slice clarity. can see in trait bound lifetime parameter 'a
bound for
qualifier, in other words, declaration self-contained, not depend on in external scope.
in slice, however, lifetime parameter 'a
free - defined in external scope, example, through lifetime elision. therefore, there no way slice can satisfy trait implementation. work trait should implemented this:
impl<'a, 'b> intotest<'a, &'a [u8]> &'b [u8] { fn into_test(&'a self) -> &'a [u8] { unimplemented!() } }
which compiles, although doesn't , couldn't want. can see in declaration lifetimes of slice , in trait signature disjoint, therefore slices satisfy for<'a>
-based bound.
there way @ problem. t: for<'a> intotest<'a, &'a [u8]>
bound means type t
implements trait every possible lifetime parameter of trait, function can decide lifetime wants. example, request 'static
. naturally in code &[u8]
tied vector in main method , cannot 'static
. therefore soundness violated - &[u8]
can't provide lifetime user wants, , not implement for<'a> intotest<'a, &'a [u8]>
.
note adding lifetime parameter generic function won't work either:
fn higher_ranked_lifetime<'a, t>(test: t) t: intotest<'a, &'a [u8]> { let _t = test.into_test(); }
there error:
<anon>:12:14: 12:18 error: `test` not live long enough <anon>:12 let _t = test.into_test(); ^~~~ <anon>:11:79: 13:2 note: reference must valid lifetime 'a defined on block @ 11:78... <anon>:11 fn higher_ranked_lifetime<'a, t>(test: t) t: intotest<'a, &'a [u8]> { <anon>:12 let _t = test.into_test(); <anon>:13 } <anon>:11:79: 13:2 note: ...but borrowed value valid scope of parameters function @ 11:78 <anon>:11 fn higher_ranked_lifetime<'a, t>(test: t) t: intotest<'a, &'a [u8]> { <anon>:12 let _t = test.into_test(); <anon>:13 }
and again correct. remember trait defined this:
pub trait intotest<'a, t> { fn into_test(&'a self) -> t self: sized; }
here require self
passed reference same lifetime lifetime parameter of trait. however, above declaration of generic function makes method not callable in principle:
fn higher_ranked_lifetime<'a, t>(test: t) t: intotest<'a, &'a [u8]>
here trait specified have lifetime parameter equal lifetime parameter of function. however, test
parameter lives through body of function. therefore, reference taken test
, including implicit 1 when calling into_test()
:
let _t = (&test).into_test();
will have lifetime strictly less lifetime parameter, , can't used parameter into_test()
method. error about.
because didn't explain need, it's hard should do. guess 1 of general ways drop lifetime parameter on trait , make trait method accept self
value, , fix generic function accordingly:
pub trait intotest<t> { fn into_test(self) -> t; } impl<'a> intotest<&'a [u8]> &'a [u8] { fn into_test(self) -> &'a [u8] { self } } fn higher_ranked_lifetime<'a, t>(test: t) t: intotest<&'a [u8]> { let _t = test.into_test(); } fn main() { println!("hello, world!"); let vec = vec![1u8]; let slice = &vec[..]; higher_ranked_lifetime(slice); }
this does work because trait not have lifetime parameters , not add requirements on how call it. lifetime parameters moved types implement it.
Comments
Post a Comment