what differences between specifiying lifetime parameter on impl item or on method signature directly?
for example, deref trait has following signature:
pub trait deref { type target: ?sized; fn deref(&'a self) -> &'a self::target; } i implement without naming lifetimes, since elided anyway.
however, in example docs looks this:
struct derefexample<t> { value: t } impl<t> deref derefexample<t> { type target = t; fn deref<'a>(&'a self) -> &'a t { &self.value } } this works , good. if changed (specifying lifetime parameter 'a on impl instead of method):
struct derefexample<t> { value: t } impl<'a, t> deref derefexample<t> { type target = t; fn deref(&'a self) -> &'a t { &self.value } } i following error:
<anon>:10:5: 12:6 error: method `deref` has incompatible type trait: expected bound lifetime parameter 'a, found concrete lifetime [e0053] <anon>:10 fn deref(&'a self) -> &'a t { <anon>:11 &self.value <anon>:12 } this confuses me. method's signature no different 1 docs. in addition, thought difference between specifiying lifetime parameter on impl or on method directly in scope of parameter only. can used in entire impl block instead of method. missing here?
yes, there difference.
the method's signature no different 1 docs.
the fact looks in docs fault of rustdoc. guess worth creating ticket in rust issue tracker, if there no 1 yet. if press [src] link in upper right corner, redirected actual source of deref, looks follows (i've removed attributes , comments):
pub trait deref { type target: ?sized; fn deref<'a>(&'a self) -> &'a self::target; } you can see deref() declared have lifetime parameter.
i thought difference between specifiying lifetime parameter on impl or on method directly in scope of parameter only.
and wrong. difference not in scope only. don't think able provide convincing side-by-side examples semantic difference visible, consider following reasoning.
first, lifetime parameters no different generic type parameters. no coincidence use similar declaration syntax. generic parameters, lifetime parameters participate in method/function signature, if want implement trait has method lifetime parameters, implementation must have same lifetime parameters (modulo possible renaming).
second, lifetime parameters in impl signature used express different kinds of lifetime relationship on functions. methods, always caller determines actual lifetime parameter want use. is, again, similar how generic methods work - caller may instantiate type parameters type need. important, deref in particular - want implements deref may dereffed lifetime of reference method called on, not else.
with impl, however, lifetime parameter chosen not when method uses parameter called, when appropriate impl chosen compiler. may (and so) based on type of value, precludes user specifying arbitrary lifetimes when method called. example:
struct bytes<'a>(&'a [u8]); impl<'a> str<'a> { fn first_two(&self) -> &'a [u8] { &self.0[..2] } } here first_two() method returns slice lifetime of value stored inside bytes structure. caller of method can't decide lifetime want - fixed lifetime of slice inside structure method called on. impossible bring lifetime parameter down method while keeping same semantics, guess can see why.
granted, in case lifetime parameter specified not participate neither in signature of impl nor in associated types, theoretically could used if declared on each function separately (because can arbitrary when method called), reasoning method signatures (provided above) kicks in.
Comments
Post a Comment