You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: common.rs
    path of file: ./repos/prusti-dev/prusti-contracts/prusti-specs/src/extern_spec_rewriter
    
    the code of the file until where you have to start completion: use crate::{
    common::{HasAttributes, HasSignature},
    extract_prusti_attributes, generate_spec_and_assertions,
    span_overrider::SpanOverrider,
    untyped::AnyFnItem,
    ExternSpecKind, RewritableReceiver, SelfTypeRewriter,
};
use itertools::Itertools;
use proc_macro2::TokenStream;
use quote::{format_ident, quote, quote_spanned, ToTokens};
use syn::{
    parse_quote_spanned, punctuated::Punctuated, spanned::Spanned, visit::Visit,
    visit_mut::VisitMut, Expr, FnArg, GenericArgument, GenericParam, Pat, PatType, Token,
};

/// Counts the number of elided lifetimes in receivers and types.
/// For details see the function `with_explicit_lifetimes`.
struct ElidedLifetimeCounter {
    num_elided_lifetimes: u32,
}

impl ElidedLifetimeCounter {
    fn new() -> ElidedLifetimeCounter {
        ElidedLifetimeCounter {
            num_elided_lifetimes: 0,
        }
    }
}

impl<'ast> syn::visit::Visit<'ast> for ElidedLifetimeCounter {
    fn visit_receiver(&mut self, receiver: &syn::Receiver) {
        if let Some((_, None)) = receiver.reference {
            self.num_elided_lifetimes += 1;
        }
    }

    fn visit_type_reference(&mut self, reference: &syn::TypeReference) {
        if reference.lifetime.is_none() {
            self.num_elided_lifetimes += 1;
        }
    }
}

fn has_multiple_elided_lifetimes(inputs
    
fn with_explicit_lifetimes(sig: &syn::Signature) -> Option<syn::Signature> {
    // This struct is responsible for inserting an explicit lifetime for elided
    // lifetimes in the receiver and output type.
    struct SelfLifetimeInserter {}

    impl syn::visit_mut::VisitMut for SelfLifetimeInserter {
        fn visit_type_reference_mut(&mut self, reference: &mut syn::TypeReference) {
            reference.lifetime = parse_quote_spanned! {reference.span() => 'prusti_self_lifetime };
        }

        fn visit_receiver_mut(&mut self, receiver: &mut syn::Receiver) {
            receiver.reference.as_mut().unwrap().1 =
                parse_quote_spanned! {receiver.span() => 'prusti_self_lifetime };
        }
    }

    if !returns_reference_with_elided_lifetime(&sig.output)
        || !has_multiple_elided_lifetimes(&sig.inputs)
    {
        return None;
    }
    let mut new_sig = sig.clone();
    let mut inserter = SelfLifetimeInserter {};

    // Insert explicit lifetime parameter to method signature
    new_sig.generics.params.insert(
        0,
        parse_quote_spanned! {new_sig.generics.params.span() => 'prusti_self_lifetime },
    );

    // Assign the explicit lifetime to the reference to self
    if let Some(syn::FnArg::Receiver(r)) = new_sig.inputs.first_mut() {
        inserter.visit_receiver_mut(r)
    }

    // Assign the explicit lifetime to references in the output
    inserter.visit_return_type_mut(&mut new_sig.output);
    Some(new_sig)
}