rustlifetime

Minimum between two lifetimes


I'm doing some lifetimes exercises from this repo (lifetimekata) with regard to the exercise 02_lifetimes_explained -> only_if_greater_hard I have a different solution that the proposed one

This is the original unannotated function which is:

#[require_lifetimes(!)]
pub fn only_if_greater_hard(
    number: & i32,
    greater_than: & i32,
    otherwise: & i32,
) -> &'d i32
{
    if number > greater_than {
        number
    } else {
        otherwise
    }
}

My solutions was this one:

#[require_lifetimes(!)]
pub fn only_if_greater_hard<'a, 'b, 'c, 'd>(
    number: &'a i32,
    greater_than: &'b i32,
    otherwise: &'c i32,
) -> &'d i32
where
    'a: 'd,
    'c: 'd,
{
    if number > greater_than {
        number
    } else {
        otherwise
    }
}

I haven't found much about lifetimes syntax so I was struggling to express "'d lifetime is min('a, 'c)" so I have expressed the opposite namely "'a outlives 'd and 'c outlives 'd" (subquestion, is there an alternative syntax or did I do it right?)

The solution provided was:

#[require_lifetimes(!)]
pub fn only_if_greater_hard<'a, 'b>(
    number: &'a i32,
    greater_than: &'b i32,
    otherwise: &'a i32,
) -> &'a i32 {
    if number > greater_than {
        number
    } else {
        otherwise
    }
}

But wouldn't this be more restrictive than what I have written? Meaning that the compiler would reject safe code since it's not required that "number" and "otherwise" have the same lifetime?


Solution

  • Using the same annotation is identical to how you solved it. Just easier to read.

    This:

    fn foo<'a>(arg1: &'a (), arg2: &'a (), arg3: &'a ()) -> &'a () {
        todo!()
    }
    

    Is equivalent to this:

    fn foo<'a, 'b, 'c, 'out>(arg1: &'a (), arg2: &'b (), arg3: &'c ()) -> &'out ()
    where 
        'a: 'out, // 'a is longer or equal to 'out
        'b: 'out,
        'c: 'out,
        // All inputs live longer than output,
        // so any is valid to return.
    {
        todo!()
    }
    

    (I could not find the page out of the Rust reference/book that describes this behavior)

    Further

    Lifetime annotations describe relationships, they do not dictate the exact lifetime.

    pub fn only_if_greater_hard<'a>(
        number: &'a i32,
        greater_than: &i32,
        otherwise: &'a i32,
    ) -> &'a i32
    {
        if number > greater_than {
            number
        } else {
            otherwise
        }
    }
    

    Here, the return value could be number or otherwise. greater_than is never returned so it doesn't even need an annotation. (It is automatically given an unnamed annotation, '0). It is perfectly fine to call this with differing lifetimes, it will just return a value with the shortest lifetime. Rust playground